You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by GitBox <gi...@apache.org> on 2022/03/18 11:09:03 UTC

[GitHub] [pulsar] Technoboy- opened a new pull request #14747: Refactor PulsarAuthorizationProvider.

Technoboy- opened a new pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747


   ### Motivation
   
   PulsarAuthorizationProvider has many duplicate codes and some logic is un-readable.
   
   ### Modifications
   - `canConsumeAsync` : remove permissionFuture
   - `allowConsumeOrProduceOpsAsync`: Using Set to avoid duplicate codes.
   - `grantPermissionAsync`: make fully async.
   - `checkPermission`: make fully async.
   - `path` : remove this unsed method.
   ### Documentation
     
   - [x] `no-need-doc` 
   
   
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] nodece commented on pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
nodece commented on pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#issuecomment-1074732511


   @Technoboy-  I notice that no tests to cover the PulsarAuthorizationProvider, could you add some tests for this?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] codelipenghui commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
codelipenghui commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r831148981



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -178,36 +156,13 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<Boolean>();
-        canProduceAsync(topicName, role, authenticationData).whenComplete((produceAuthorized, ex) -> {
-            if (ex == null) {
-                if (produceAuthorized) {
-                    finalResult.complete(produceAuthorized);
-                    return;
-                }
-            } else {
-                if (log.isDebugEnabled()) {
-                    log.debug(
-                            "Topic [{}] Role [{}] exception occurred while trying to check Produce permissions. {}",
-                            topicName.toString(), role, ex.getMessage());

Review comment:
       Same as the above comment.

##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -106,63 +104,43 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData, String subscription) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
-                    .thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for topic : {}", topicName);
-                    }
-                } else {
-                    if (isNotBlank(subscription)) {
-                        // validate if role is authorize to access subscription. (skip validatation if authorization
-                        // list is empty)
-                        Set<String> roles = policies.get().auth_policies
-                                .getSubscriptionAuthentication().get(subscription);
-                        if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
-                            log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
-                            permissionFuture.complete(false);
-                            return;
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
+                .thenCompose(policies -> {
+                    if (!policies.isPresent()) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Policies node couldn't be found for topic : {}", topicName);
                         }
+                    } else {
+                        if (isNotBlank(subscription)) {
+                            // validate if role is authorized to access subscription. (skip validation if authorization
+                            // list is empty)
+                            Set<String> roles = policies.get().auth_policies
+                                    .getSubscriptionAuthentication().get(subscription);
+                            if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
+                                log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
+                                return CompletableFuture.completedFuture(false);
+                            }
 
-                        // validate if subscription-auth mode is configured
-                        switch (policies.get().subscription_auth_mode) {
-                        case Prefix:
-                            if (!subscription.startsWith(role)) {
-                                PulsarServerException ex = new PulsarServerException(String.format(
-                                        "Failed to create consumer - The subscription name needs to be prefixed by the "
-                                                + "authentication role, like %s-xxxx for topic: %s", role, topicName));
-                                permissionFuture.completeExceptionally(ex);
-                                return;
+                            // validate if subscription-auth mode is configured
+                            if (policies.get().subscription_auth_mode != null) {
+                                switch (policies.get().subscription_auth_mode) {
+                                    case Prefix:
+                                        if (!subscription.startsWith(role)) {
+                                            PulsarServerException ex = new PulsarServerException(String.format(
+                                                 "Failed to create consumer - The subscription name needs to be"
+                                                 + " prefixed by the authentication role, like %s-xxxx for topic: %s",
+                                                 role, topicName));
+                                            return FutureUtil.failedFuture(ex);
+                                        }
+                                        break;
+                                    default:
+                                        break;
+                                }
                             }
-                            break;
-                        default:
-                            break;
                         }
                     }
-                }
-                // check namespace and topic level consume-permissions
-                checkAuthorization(topicName, role, AuthAction.consume).thenAccept(isAuthorized -> {
-                    permissionFuture.complete(isAuthorized);
-                }).exceptionally(ex -> {
-                    log.warn("Client with Role - {} failed to get permissions for topic - {}. {}", role, topicName,
-                            ex.getMessage());
-                    permissionFuture.completeExceptionally(ex);
-                    return null;
+                    return checkAuthorization(topicName, role, AuthAction.consume);
                 });
-            }).exceptionally(ex -> {
-                log.warn("Client with Role - {} failed to get permissions for topic - {}. {}", role, topicName,
-                        ex.getMessage());
-                permissionFuture.completeExceptionally(ex);
-                return null;
-            });
-        } catch (Exception e) {
-            log.warn("Client  with Role - {} failed to get permissions for topic - {}. {}", role, topicName,

Review comment:
       After this change, we will remove this log? We'd better keep the behavior will not be changed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] eolivelli commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
eolivelli commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r829981461



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -231,185 +184,149 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     private CompletableFuture<Boolean> allowConsumeOrProduceOpsAsync(NamespaceName namespaceName,
                                                                      String role,
                                                                      AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<>();
-        allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
-                .whenComplete((consumeAuthorized, e) -> {
-                    if (e == null) {
-                        if (consumeAuthorized) {
-                            finalResult.complete(consumeAuthorized);
-                            return;
-                        }
-                    } else {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Namespace [{}] Role [{}] exception occurred while trying to check Consume "
-                                    + "permission. {}", namespaceName, role, e.getCause());
-                        }
+        return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
+                .thenCompose(canConsumer -> {
+                    if (canConsumer) {
+                        return CompletableFuture.completedFuture(true);
                     }
-                    allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce)
-                            .whenComplete((produceAuthorized, ex) -> {
-                                if (ex == null) {
-                                    finalResult.complete(produceAuthorized);
-                                } else {
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Namespace [{}] Role [{}] exception occurred while trying to check "
-                                                + "Produce permission. {}", namespaceName, role, ex.getCause());
-                                    }
-                                    finalResult.completeExceptionally(ex.getCause());
-                                }
-                            });
+                    return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce);
                 });
-
-        return finalResult;
     }
 
     private CompletableFuture<Boolean> allowTheSpecifiedActionOpsAsync(NamespaceName namespaceName, String role,
                                                                        AuthenticationDataSource authenticationData,
                                                                        AuthAction authAction) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
-                    }
-                } else {
-                    Map<String, Set<AuthAction>> namespaceRoles = policies.get()
-                            .auth_policies.getNamespaceAuthentication();
-                    Set<AuthAction> namespaceActions = namespaceRoles.get(role);
-                    if (namespaceActions != null && namespaceActions.contains(authAction)) {
-                        // The role has namespace level permission
-                        permissionFuture.complete(true);
-                        return;
-                    }
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenApply(policies -> {
+            if (!policies.isPresent()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
+                }
+            } else {
+                Map<String, Set<AuthAction>> namespaceRoles = policies.get()
+                        .auth_policies.getNamespaceAuthentication();

Review comment:
       I believe that we could think more about this objects (like auth_policies  here) that can be null

##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -106,63 +104,41 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData, String subscription) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
-                    .thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for topic : {}", topicName);
-                    }
-                } else {
-                    if (isNotBlank(subscription)) {
-                        // validate if role is authorize to access subscription. (skip validatation if authorization
-                        // list is empty)
-                        Set<String> roles = policies.get().auth_policies
-                                .getSubscriptionAuthentication().get(subscription);
-                        if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
-                            log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
-                            permissionFuture.complete(false);
-                            return;
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
+                .thenCompose(policies -> {
+                    if (!policies.isPresent()) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Policies node couldn't be found for topic : {}", topicName);
                         }
+                    } else {
+                        if (isNotBlank(subscription)) {
+                            // validate if role is authorize to access subscription. (skip validatation if authorization
+                            // list is empty)
+                            Set<String> roles = policies.get().auth_policies
+                                    .getSubscriptionAuthentication().get(subscription);
+                            if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
+                                log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
+                                return CompletableFuture.completedFuture(false);
+                            }
 
-                        // validate if subscription-auth mode is configured
-                        switch (policies.get().subscription_auth_mode) {
-                        case Prefix:
-                            if (!subscription.startsWith(role)) {
-                                PulsarServerException ex = new PulsarServerException(String.format(
-                                        "Failed to create consumer - The subscription name needs to be prefixed by the "
-                                                + "authentication role, like %s-xxxx for topic: %s", role, topicName));
-                                permissionFuture.completeExceptionally(ex);
-                                return;
+                            // validate if subscription-auth mode is configured
+                            switch (policies.get().subscription_auth_mode) {

Review comment:
       this `subscription_auth_mode`  may be null 

##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -106,63 +104,41 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData, String subscription) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
-                    .thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for topic : {}", topicName);
-                    }
-                } else {
-                    if (isNotBlank(subscription)) {
-                        // validate if role is authorize to access subscription. (skip validatation if authorization
-                        // list is empty)
-                        Set<String> roles = policies.get().auth_policies
-                                .getSubscriptionAuthentication().get(subscription);
-                        if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
-                            log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
-                            permissionFuture.complete(false);
-                            return;
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
+                .thenCompose(policies -> {
+                    if (!policies.isPresent()) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Policies node couldn't be found for topic : {}", topicName);
                         }
+                    } else {
+                        if (isNotBlank(subscription)) {
+                            // validate if role is authorize to access subscription. (skip validatation if authorization
+                            // list is empty)
+                            Set<String> roles = policies.get().auth_policies

Review comment:
       this `auth_policies` may be null




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] Technoboy- commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
Technoboy- commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r831693036



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -106,63 +104,43 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData, String subscription) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
-                    .thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for topic : {}", topicName);
-                    }
-                } else {
-                    if (isNotBlank(subscription)) {
-                        // validate if role is authorize to access subscription. (skip validatation if authorization
-                        // list is empty)
-                        Set<String> roles = policies.get().auth_policies
-                                .getSubscriptionAuthentication().get(subscription);
-                        if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
-                            log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
-                            permissionFuture.complete(false);
-                            return;
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
+                .thenCompose(policies -> {
+                    if (!policies.isPresent()) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Policies node couldn't be found for topic : {}", topicName);
                         }
+                    } else {
+                        if (isNotBlank(subscription)) {
+                            // validate if role is authorized to access subscription. (skip validation if authorization
+                            // list is empty)
+                            Set<String> roles = policies.get().auth_policies
+                                    .getSubscriptionAuthentication().get(subscription);
+                            if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
+                                log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
+                                return CompletableFuture.completedFuture(false);
+                            }
 
-                        // validate if subscription-auth mode is configured
-                        switch (policies.get().subscription_auth_mode) {
-                        case Prefix:
-                            if (!subscription.startsWith(role)) {
-                                PulsarServerException ex = new PulsarServerException(String.format(
-                                        "Failed to create consumer - The subscription name needs to be prefixed by the "
-                                                + "authentication role, like %s-xxxx for topic: %s", role, topicName));
-                                permissionFuture.completeExceptionally(ex);
-                                return;
+                            // validate if subscription-auth mode is configured
+                            if (policies.get().subscription_auth_mode != null) {
+                                switch (policies.get().subscription_auth_mode) {
+                                    case Prefix:
+                                        if (!subscription.startsWith(role)) {
+                                            PulsarServerException ex = new PulsarServerException(String.format(
+                                                 "Failed to create consumer - The subscription name needs to be"
+                                                 + " prefixed by the authentication role, like %s-xxxx for topic: %s",
+                                                 role, topicName));
+                                            return FutureUtil.failedFuture(ex);
+                                        }
+                                        break;
+                                    default:
+                                        break;
+                                }
                             }
-                            break;
-                        default:
-                            break;
                         }
                     }
-                }
-                // check namespace and topic level consume-permissions
-                checkAuthorization(topicName, role, AuthAction.consume).thenAccept(isAuthorized -> {
-                    permissionFuture.complete(isAuthorized);
-                }).exceptionally(ex -> {
-                    log.warn("Client with Role - {} failed to get permissions for topic - {}. {}", role, topicName,
-                            ex.getMessage());
-                    permissionFuture.completeExceptionally(ex);
-                    return null;
+                    return checkAuthorization(topicName, role, AuthAction.consume);
                 });
-            }).exceptionally(ex -> {
-                log.warn("Client with Role - {} failed to get permissions for topic - {}. {}", role, topicName,
-                        ex.getMessage());
-                permissionFuture.completeExceptionally(ex);
-                return null;
-            });
-        } catch (Exception e) {
-            log.warn("Client  with Role - {} failed to get permissions for topic - {}. {}", role, topicName,

Review comment:
       ok, done.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] Technoboy- commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
Technoboy- commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r834066915



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -178,36 +160,20 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<Boolean>();
-        canProduceAsync(topicName, role, authenticationData).whenComplete((produceAuthorized, ex) -> {
-            if (ex == null) {
-                if (produceAuthorized) {
-                    finalResult.complete(produceAuthorized);
-                    return;
-                }
-            } else {
-                if (log.isDebugEnabled()) {
-                    log.debug(
-                            "Topic [{}] Role [{}] exception occurred while trying to check Produce permissions. {}",
-                            topicName.toString(), role, ex.getMessage());
-                }
-            }
-            canConsumeAsync(topicName, role, authenticationData, null).whenComplete((consumeAuthorized, e)
-                    -> {
-                if (e == null) {
-                    finalResult.complete(consumeAuthorized);
-                } else {
+        return canProduceAsync(topicName, role, authenticationData)
+                .thenCompose(canProduce -> {
+                    if (canProduce) {
+                        return CompletableFuture.completedFuture(true);
+                    }
+                    return canConsumeAsync(topicName, role, authenticationData, null);
+                }).exceptionally(ex -> {
                     if (log.isDebugEnabled()) {
-                        log.debug(
-                                "Topic [{}] Role [{}] exception occurred while trying to check Consume permissions. {}",
-                                topicName.toString(), role, e.getMessage());
+                        log.debug("Topic [{}] Role [{}] exception occurred while trying to check produce/consume"
+                                + " permissions. {}", topicName.toString(), role, ex.getMessage());
 
                     }
-                    finalResult.completeExceptionally(e);
-                }
-            });
-        });
-        return finalResult;
+                    return null;

Review comment:
       fixed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] Technoboy- commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
Technoboy- commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r830423956



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -231,185 +184,149 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     private CompletableFuture<Boolean> allowConsumeOrProduceOpsAsync(NamespaceName namespaceName,
                                                                      String role,
                                                                      AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<>();
-        allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
-                .whenComplete((consumeAuthorized, e) -> {
-                    if (e == null) {
-                        if (consumeAuthorized) {
-                            finalResult.complete(consumeAuthorized);
-                            return;
-                        }
-                    } else {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Namespace [{}] Role [{}] exception occurred while trying to check Consume "
-                                    + "permission. {}", namespaceName, role, e.getCause());
-                        }
+        return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
+                .thenCompose(canConsumer -> {
+                    if (canConsumer) {
+                        return CompletableFuture.completedFuture(true);
                     }
-                    allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce)
-                            .whenComplete((produceAuthorized, ex) -> {
-                                if (ex == null) {
-                                    finalResult.complete(produceAuthorized);
-                                } else {
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Namespace [{}] Role [{}] exception occurred while trying to check "
-                                                + "Produce permission. {}", namespaceName, role, ex.getCause());
-                                    }
-                                    finalResult.completeExceptionally(ex.getCause());
-                                }
-                            });
+                    return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce);
                 });
-
-        return finalResult;
     }
 
     private CompletableFuture<Boolean> allowTheSpecifiedActionOpsAsync(NamespaceName namespaceName, String role,
                                                                        AuthenticationDataSource authenticationData,
                                                                        AuthAction authAction) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
-                    }
-                } else {
-                    Map<String, Set<AuthAction>> namespaceRoles = policies.get()
-                            .auth_policies.getNamespaceAuthentication();
-                    Set<AuthAction> namespaceActions = namespaceRoles.get(role);
-                    if (namespaceActions != null && namespaceActions.contains(authAction)) {
-                        // The role has namespace level permission
-                        permissionFuture.complete(true);
-                        return;
-                    }
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenApply(policies -> {
+            if (!policies.isPresent()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
+                }
+            } else {
+                Map<String, Set<AuthAction>> namespaceRoles = policies.get()
+                        .auth_policies.getNamespaceAuthentication();

Review comment:
       Hi @eolivelli . Seems safe, because it is final. But thanks for your reminder, I will check the other fields.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] zymap commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
zymap commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r833890936



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -231,185 +197,149 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     private CompletableFuture<Boolean> allowConsumeOrProduceOpsAsync(NamespaceName namespaceName,
                                                                      String role,
                                                                      AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<>();
-        allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
-                .whenComplete((consumeAuthorized, e) -> {
-                    if (e == null) {
-                        if (consumeAuthorized) {
-                            finalResult.complete(consumeAuthorized);
-                            return;
-                        }
-                    } else {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Namespace [{}] Role [{}] exception occurred while trying to check Consume "
-                                    + "permission. {}", namespaceName, role, e.getCause());
-                        }
+        return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
+                .thenCompose(canConsumer -> {
+                    if (canConsumer) {
+                        return CompletableFuture.completedFuture(true);
                     }
-                    allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce)
-                            .whenComplete((produceAuthorized, ex) -> {
-                                if (ex == null) {
-                                    finalResult.complete(produceAuthorized);
-                                } else {
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Namespace [{}] Role [{}] exception occurred while trying to check "
-                                                + "Produce permission. {}", namespaceName, role, ex.getCause());
-                                    }
-                                    finalResult.completeExceptionally(ex.getCause());
-                                }
-                            });
+                    return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce);
                 });
-
-        return finalResult;
     }
 
     private CompletableFuture<Boolean> allowTheSpecifiedActionOpsAsync(NamespaceName namespaceName, String role,
                                                                        AuthenticationDataSource authenticationData,
                                                                        AuthAction authAction) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
-                    }
-                } else {
-                    Map<String, Set<AuthAction>> namespaceRoles = policies.get()
-                            .auth_policies.getNamespaceAuthentication();
-                    Set<AuthAction> namespaceActions = namespaceRoles.get(role);
-                    if (namespaceActions != null && namespaceActions.contains(authAction)) {
-                        // The role has namespace level permission
-                        permissionFuture.complete(true);
-                        return;
-                    }
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenApply(policies -> {
+            if (!policies.isPresent()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
+                }
+            } else {
+                Map<String, Set<AuthAction>> namespaceRoles = policies.get()
+                        .auth_policies.getNamespaceAuthentication();
+                Set<AuthAction> namespaceActions = namespaceRoles.get(role);
+                if (namespaceActions != null && namespaceActions.contains(authAction)) {
+                    // The role has namespace level permission
+                    return true;
+                }
 
-                    // Using wildcard
-                    if (conf.isAuthorizationAllowWildcardsMatching()) {
-                        if (checkWildcardPermission(role, authAction, namespaceRoles)) {
-                            // The role has namespace level permission by wildcard match
-                            permissionFuture.complete(true);
-                            return;
-                        }
+                // Using wildcard
+                if (conf.isAuthorizationAllowWildcardsMatching()) {
+                    if (checkWildcardPermission(role, authAction, namespaceRoles)) {
+                        // The role has namespace level permission by wildcard match
+                        return true;
                     }
                 }
-                permissionFuture.complete(false);
-            }).exceptionally(ex -> {
-                log.warn("Client  with Role - {} failed to get permissions for namespace - {}. {}", role, namespaceName,
-                        ex.getMessage());
-                permissionFuture.completeExceptionally(ex);
-                return null;
-            });
-        } catch (Exception e) {
-            log.warn("Client  with Role - {} failed to get permissions for namespace - {}. {}", role, namespaceName,
-                    e.getMessage());
-            permissionFuture.completeExceptionally(e);
-        }
-        return permissionFuture;
+            }
+            return false;
+        });
     }
 
     @Override
     public CompletableFuture<Void> grantPermissionAsync(TopicName topicName, Set<AuthAction> actions,
-            String role, String authDataJson) {
-        try {
-            validatePoliciesReadOnlyAccess();
-        } catch (Exception e) {
-            return FutureUtil.failedFuture(e);
-        }
+                                                        String role, String authDataJson) {
 
-        String topicUri = topicName.toString();
-        return pulsarResources.getNamespaceResources()
-                .setPoliciesAsync(topicName.getNamespaceObject(), policies -> {
-                    policies.auth_policies.getTopicAuthentication()
-                            .computeIfAbsent(topicUri, __ -> new HashMap<>())
-                            .put(role, actions);
-                    return policies;
-                }).whenComplete((__, throwable) -> {
-                    if (throwable != null) {
-                        log.error("[{}] Failed to set permissions for role {} on topic {}", role, role, topicName,
-                                throwable);
-                    } else {
-                        log.info("[{}] Successfully granted access for role {}: {} - topic {}", role, role, actions,
-                                topicUri);
-                    }
-                });
+        return getPoliciesReadOnlyAsync().thenCompose(readonly -> {
+            if (readonly) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies are read-only. Broker cannot do read-write operations");
+                }
+                throw new IllegalStateException("policies are in readonly mode");
+            }
+            String topicUri = topicName.toString();
+            return pulsarResources.getNamespaceResources()
+                    .setPoliciesAsync(topicName.getNamespaceObject(), policies -> {
+                        policies.auth_policies.getTopicAuthentication()
+                                .computeIfAbsent(topicUri, __ -> new HashMap<>())
+                                .put(role, actions);
+                        return policies;
+                    }).whenComplete((__, ex) -> {
+                        if (ex != null) {
+                            log.error("Failed to set permissions for role {} on topic {}", role, topicName, ex);
+                        } else {
+                            log.info("Successfully granted access for role {}: {} - topic {}", role, actions, topicUri);
+                        }
+                    });
+        });
     }
 
     @Override
     public CompletableFuture<Void> grantPermissionAsync(NamespaceName namespaceName, Set<AuthAction> actions,
-            String role, String authDataJson) {
-        try {
-            validatePoliciesReadOnlyAccess();
-        } catch (Exception e) {
-            return FutureUtil.failedFuture(e);
-        }
-
-        return pulsarResources.getNamespaceResources()
-                .setPoliciesAsync(namespaceName, policies -> {
-                    policies.auth_policies.getNamespaceAuthentication().put(role, actions);
-                    return policies;
-                }).whenComplete((__, throwable) -> {
-                    if (throwable != null) {
-                        log.error("[{}] Failed to set permissions for role {} namespace {}", role, role, namespaceName,
-                                throwable);
-                    } else {
-                        log.info("[{}] Successfully granted access for role {}: {} - namespace {}", role, role, actions,
-                                namespaceName);
-                    }
-                });
+                                                        String role, String authDataJson) {
+        return getPoliciesReadOnlyAsync().thenCompose(readonly -> {
+            if (readonly) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies are read-only. Broker cannot do read-write operations");
+                }
+                throw new IllegalStateException("policies are in readonly mode");

Review comment:
       If no one catches the exception, the future will never be completed. For example:
   
   ```
           CompletableFuture future = new CompletableFuture();
           future.thenRun(() -> {
               System.out.println("first thing");
           }).thenCompose(b -> {
               throw new IllegalArgumentException("fail future");
           }).thenRun(() -> {
               System.out.println("other things");
           });
           future.get();
   ```
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] Technoboy- commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
Technoboy- commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r830423195



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -106,63 +104,41 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData, String subscription) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
-                    .thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for topic : {}", topicName);
-                    }
-                } else {
-                    if (isNotBlank(subscription)) {
-                        // validate if role is authorize to access subscription. (skip validatation if authorization
-                        // list is empty)
-                        Set<String> roles = policies.get().auth_policies
-                                .getSubscriptionAuthentication().get(subscription);
-                        if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
-                            log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
-                            permissionFuture.complete(false);
-                            return;
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
+                .thenCompose(policies -> {
+                    if (!policies.isPresent()) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Policies node couldn't be found for topic : {}", topicName);
                         }
+                    } else {
+                        if (isNotBlank(subscription)) {
+                            // validate if role is authorize to access subscription. (skip validatation if authorization
+                            // list is empty)
+                            Set<String> roles = policies.get().auth_policies

Review comment:
       Hi @eolivelli , I re-check the code, and field `auth_policies ` is `final`.
   ```
   public final AuthPolicies auth_policies = AuthPolicies.builder().build();
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] Technoboy- commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
Technoboy- commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r831692970



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -178,36 +156,13 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<Boolean>();
-        canProduceAsync(topicName, role, authenticationData).whenComplete((produceAuthorized, ex) -> {
-            if (ex == null) {
-                if (produceAuthorized) {
-                    finalResult.complete(produceAuthorized);
-                    return;
-                }
-            } else {
-                if (log.isDebugEnabled()) {
-                    log.debug(
-                            "Topic [{}] Role [{}] exception occurred while trying to check Produce permissions. {}",
-                            topicName.toString(), role, ex.getMessage());

Review comment:
       ok, yes, done.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] zymap commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
zymap commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r833887459



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -178,36 +160,20 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<Boolean>();
-        canProduceAsync(topicName, role, authenticationData).whenComplete((produceAuthorized, ex) -> {
-            if (ex == null) {
-                if (produceAuthorized) {
-                    finalResult.complete(produceAuthorized);
-                    return;
-                }
-            } else {
-                if (log.isDebugEnabled()) {
-                    log.debug(
-                            "Topic [{}] Role [{}] exception occurred while trying to check Produce permissions. {}",
-                            topicName.toString(), role, ex.getMessage());
-                }
-            }
-            canConsumeAsync(topicName, role, authenticationData, null).whenComplete((consumeAuthorized, e)
-                    -> {
-                if (e == null) {
-                    finalResult.complete(consumeAuthorized);
-                } else {
+        return canProduceAsync(topicName, role, authenticationData)
+                .thenCompose(canProduce -> {
+                    if (canProduce) {
+                        return CompletableFuture.completedFuture(true);
+                    }
+                    return canConsumeAsync(topicName, role, authenticationData, null);
+                }).exceptionally(ex -> {
                     if (log.isDebugEnabled()) {
-                        log.debug(
-                                "Topic [{}] Role [{}] exception occurred while trying to check Consume permissions. {}",
-                                topicName.toString(), role, e.getMessage());
+                        log.debug("Topic [{}] Role [{}] exception occurred while trying to check produce/consume"
+                                + " permissions. {}", topicName.toString(), role, ex.getMessage());
 
                     }
-                    finalResult.completeExceptionally(e);
-                }
-            });
-        });
-        return finalResult;
+                    return null;

Review comment:
       Looks like this will change the original behaviors. We used to return an exceptional CompletableFuture so the caller will know the CompletableFuture is failed. If we return null in the `exceptionally` method, the caller will receive null and if there has someone use it, it will cause a NPE.

##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -231,185 +197,149 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     private CompletableFuture<Boolean> allowConsumeOrProduceOpsAsync(NamespaceName namespaceName,
                                                                      String role,
                                                                      AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<>();
-        allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
-                .whenComplete((consumeAuthorized, e) -> {
-                    if (e == null) {
-                        if (consumeAuthorized) {
-                            finalResult.complete(consumeAuthorized);
-                            return;
-                        }
-                    } else {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Namespace [{}] Role [{}] exception occurred while trying to check Consume "
-                                    + "permission. {}", namespaceName, role, e.getCause());
-                        }
+        return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
+                .thenCompose(canConsumer -> {
+                    if (canConsumer) {
+                        return CompletableFuture.completedFuture(true);
                     }
-                    allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce)
-                            .whenComplete((produceAuthorized, ex) -> {
-                                if (ex == null) {
-                                    finalResult.complete(produceAuthorized);
-                                } else {
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Namespace [{}] Role [{}] exception occurred while trying to check "
-                                                + "Produce permission. {}", namespaceName, role, ex.getCause());
-                                    }
-                                    finalResult.completeExceptionally(ex.getCause());
-                                }
-                            });
+                    return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce);
                 });
-
-        return finalResult;
     }
 
     private CompletableFuture<Boolean> allowTheSpecifiedActionOpsAsync(NamespaceName namespaceName, String role,
                                                                        AuthenticationDataSource authenticationData,
                                                                        AuthAction authAction) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
-                    }
-                } else {
-                    Map<String, Set<AuthAction>> namespaceRoles = policies.get()
-                            .auth_policies.getNamespaceAuthentication();
-                    Set<AuthAction> namespaceActions = namespaceRoles.get(role);
-                    if (namespaceActions != null && namespaceActions.contains(authAction)) {
-                        // The role has namespace level permission
-                        permissionFuture.complete(true);
-                        return;
-                    }
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenApply(policies -> {
+            if (!policies.isPresent()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
+                }
+            } else {
+                Map<String, Set<AuthAction>> namespaceRoles = policies.get()
+                        .auth_policies.getNamespaceAuthentication();
+                Set<AuthAction> namespaceActions = namespaceRoles.get(role);
+                if (namespaceActions != null && namespaceActions.contains(authAction)) {
+                    // The role has namespace level permission
+                    return true;
+                }
 
-                    // Using wildcard
-                    if (conf.isAuthorizationAllowWildcardsMatching()) {
-                        if (checkWildcardPermission(role, authAction, namespaceRoles)) {
-                            // The role has namespace level permission by wildcard match
-                            permissionFuture.complete(true);
-                            return;
-                        }
+                // Using wildcard
+                if (conf.isAuthorizationAllowWildcardsMatching()) {
+                    if (checkWildcardPermission(role, authAction, namespaceRoles)) {
+                        // The role has namespace level permission by wildcard match
+                        return true;
                     }
                 }
-                permissionFuture.complete(false);
-            }).exceptionally(ex -> {
-                log.warn("Client  with Role - {} failed to get permissions for namespace - {}. {}", role, namespaceName,
-                        ex.getMessage());
-                permissionFuture.completeExceptionally(ex);
-                return null;
-            });
-        } catch (Exception e) {
-            log.warn("Client  with Role - {} failed to get permissions for namespace - {}. {}", role, namespaceName,
-                    e.getMessage());
-            permissionFuture.completeExceptionally(e);
-        }
-        return permissionFuture;
+            }
+            return false;
+        });
     }
 
     @Override
     public CompletableFuture<Void> grantPermissionAsync(TopicName topicName, Set<AuthAction> actions,
-            String role, String authDataJson) {
-        try {
-            validatePoliciesReadOnlyAccess();
-        } catch (Exception e) {
-            return FutureUtil.failedFuture(e);
-        }
+                                                        String role, String authDataJson) {
 
-        String topicUri = topicName.toString();
-        return pulsarResources.getNamespaceResources()
-                .setPoliciesAsync(topicName.getNamespaceObject(), policies -> {
-                    policies.auth_policies.getTopicAuthentication()
-                            .computeIfAbsent(topicUri, __ -> new HashMap<>())
-                            .put(role, actions);
-                    return policies;
-                }).whenComplete((__, throwable) -> {
-                    if (throwable != null) {
-                        log.error("[{}] Failed to set permissions for role {} on topic {}", role, role, topicName,
-                                throwable);
-                    } else {
-                        log.info("[{}] Successfully granted access for role {}: {} - topic {}", role, role, actions,
-                                topicUri);
-                    }
-                });
+        return getPoliciesReadOnlyAsync().thenCompose(readonly -> {
+            if (readonly) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies are read-only. Broker cannot do read-write operations");
+                }
+                throw new IllegalStateException("policies are in readonly mode");
+            }
+            String topicUri = topicName.toString();
+            return pulsarResources.getNamespaceResources()
+                    .setPoliciesAsync(topicName.getNamespaceObject(), policies -> {
+                        policies.auth_policies.getTopicAuthentication()
+                                .computeIfAbsent(topicUri, __ -> new HashMap<>())
+                                .put(role, actions);
+                        return policies;
+                    }).whenComplete((__, ex) -> {
+                        if (ex != null) {
+                            log.error("Failed to set permissions for role {} on topic {}", role, topicName, ex);
+                        } else {
+                            log.info("Successfully granted access for role {}: {} - topic {}", role, actions, topicUri);
+                        }
+                    });
+        });
     }
 
     @Override
     public CompletableFuture<Void> grantPermissionAsync(NamespaceName namespaceName, Set<AuthAction> actions,
-            String role, String authDataJson) {
-        try {
-            validatePoliciesReadOnlyAccess();
-        } catch (Exception e) {
-            return FutureUtil.failedFuture(e);
-        }
-
-        return pulsarResources.getNamespaceResources()
-                .setPoliciesAsync(namespaceName, policies -> {
-                    policies.auth_policies.getNamespaceAuthentication().put(role, actions);
-                    return policies;
-                }).whenComplete((__, throwable) -> {
-                    if (throwable != null) {
-                        log.error("[{}] Failed to set permissions for role {} namespace {}", role, role, namespaceName,
-                                throwable);
-                    } else {
-                        log.info("[{}] Successfully granted access for role {}: {} - namespace {}", role, role, actions,
-                                namespaceName);
-                    }
-                });
+                                                        String role, String authDataJson) {
+        return getPoliciesReadOnlyAsync().thenCompose(readonly -> {
+            if (readonly) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies are read-only. Broker cannot do read-write operations");
+                }
+                throw new IllegalStateException("policies are in readonly mode");

Review comment:
       If no one catches the exception, the future will never be complete. For example:
   
   ```
           CompletableFuture future = new CompletableFuture();
           future.thenRun(() -> {
               System.out.println("first thing");
           }).thenCompose(b -> {
               throw new IllegalArgumentException("fail future");
           }).thenRun(() -> {
               System.out.println("other things");
           });
           future.get();
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] eolivelli commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
eolivelli commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r829981461



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -231,185 +184,149 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     private CompletableFuture<Boolean> allowConsumeOrProduceOpsAsync(NamespaceName namespaceName,
                                                                      String role,
                                                                      AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<>();
-        allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
-                .whenComplete((consumeAuthorized, e) -> {
-                    if (e == null) {
-                        if (consumeAuthorized) {
-                            finalResult.complete(consumeAuthorized);
-                            return;
-                        }
-                    } else {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Namespace [{}] Role [{}] exception occurred while trying to check Consume "
-                                    + "permission. {}", namespaceName, role, e.getCause());
-                        }
+        return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
+                .thenCompose(canConsumer -> {
+                    if (canConsumer) {
+                        return CompletableFuture.completedFuture(true);
                     }
-                    allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce)
-                            .whenComplete((produceAuthorized, ex) -> {
-                                if (ex == null) {
-                                    finalResult.complete(produceAuthorized);
-                                } else {
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Namespace [{}] Role [{}] exception occurred while trying to check "
-                                                + "Produce permission. {}", namespaceName, role, ex.getCause());
-                                    }
-                                    finalResult.completeExceptionally(ex.getCause());
-                                }
-                            });
+                    return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce);
                 });
-
-        return finalResult;
     }
 
     private CompletableFuture<Boolean> allowTheSpecifiedActionOpsAsync(NamespaceName namespaceName, String role,
                                                                        AuthenticationDataSource authenticationData,
                                                                        AuthAction authAction) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
-                    }
-                } else {
-                    Map<String, Set<AuthAction>> namespaceRoles = policies.get()
-                            .auth_policies.getNamespaceAuthentication();
-                    Set<AuthAction> namespaceActions = namespaceRoles.get(role);
-                    if (namespaceActions != null && namespaceActions.contains(authAction)) {
-                        // The role has namespace level permission
-                        permissionFuture.complete(true);
-                        return;
-                    }
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenApply(policies -> {
+            if (!policies.isPresent()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
+                }
+            } else {
+                Map<String, Set<AuthAction>> namespaceRoles = policies.get()
+                        .auth_policies.getNamespaceAuthentication();

Review comment:
       I believe that we could think more about this objects (like auth_policies  here) that can be null

##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -106,63 +104,41 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData, String subscription) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
-                    .thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for topic : {}", topicName);
-                    }
-                } else {
-                    if (isNotBlank(subscription)) {
-                        // validate if role is authorize to access subscription. (skip validatation if authorization
-                        // list is empty)
-                        Set<String> roles = policies.get().auth_policies
-                                .getSubscriptionAuthentication().get(subscription);
-                        if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
-                            log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
-                            permissionFuture.complete(false);
-                            return;
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
+                .thenCompose(policies -> {
+                    if (!policies.isPresent()) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Policies node couldn't be found for topic : {}", topicName);
                         }
+                    } else {
+                        if (isNotBlank(subscription)) {
+                            // validate if role is authorize to access subscription. (skip validatation if authorization
+                            // list is empty)
+                            Set<String> roles = policies.get().auth_policies
+                                    .getSubscriptionAuthentication().get(subscription);
+                            if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
+                                log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
+                                return CompletableFuture.completedFuture(false);
+                            }
 
-                        // validate if subscription-auth mode is configured
-                        switch (policies.get().subscription_auth_mode) {
-                        case Prefix:
-                            if (!subscription.startsWith(role)) {
-                                PulsarServerException ex = new PulsarServerException(String.format(
-                                        "Failed to create consumer - The subscription name needs to be prefixed by the "
-                                                + "authentication role, like %s-xxxx for topic: %s", role, topicName));
-                                permissionFuture.completeExceptionally(ex);
-                                return;
+                            // validate if subscription-auth mode is configured
+                            switch (policies.get().subscription_auth_mode) {

Review comment:
       this `subscription_auth_mode`  may be null 

##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -106,63 +104,41 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData, String subscription) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
-                    .thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for topic : {}", topicName);
-                    }
-                } else {
-                    if (isNotBlank(subscription)) {
-                        // validate if role is authorize to access subscription. (skip validatation if authorization
-                        // list is empty)
-                        Set<String> roles = policies.get().auth_policies
-                                .getSubscriptionAuthentication().get(subscription);
-                        if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
-                            log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
-                            permissionFuture.complete(false);
-                            return;
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
+                .thenCompose(policies -> {
+                    if (!policies.isPresent()) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Policies node couldn't be found for topic : {}", topicName);
                         }
+                    } else {
+                        if (isNotBlank(subscription)) {
+                            // validate if role is authorize to access subscription. (skip validatation if authorization
+                            // list is empty)
+                            Set<String> roles = policies.get().auth_policies

Review comment:
       this `auth_policies` may be null




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] Technoboy- commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
Technoboy- commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r830423828



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -106,63 +104,41 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     @Override
     public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role,
             AuthenticationDataSource authenticationData, String subscription) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
-                    .thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for topic : {}", topicName);
-                    }
-                } else {
-                    if (isNotBlank(subscription)) {
-                        // validate if role is authorize to access subscription. (skip validatation if authorization
-                        // list is empty)
-                        Set<String> roles = policies.get().auth_policies
-                                .getSubscriptionAuthentication().get(subscription);
-                        if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
-                            log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
-                            permissionFuture.complete(false);
-                            return;
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(topicName.getNamespaceObject())
+                .thenCompose(policies -> {
+                    if (!policies.isPresent()) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Policies node couldn't be found for topic : {}", topicName);
                         }
+                    } else {
+                        if (isNotBlank(subscription)) {
+                            // validate if role is authorize to access subscription. (skip validatation if authorization
+                            // list is empty)
+                            Set<String> roles = policies.get().auth_policies
+                                    .getSubscriptionAuthentication().get(subscription);
+                            if (roles != null && !roles.isEmpty() && !roles.contains(role)) {
+                                log.warn("[{}] is not authorized to subscribe on {}-{}", role, topicName, subscription);
+                                return CompletableFuture.completedFuture(false);
+                            }
 
-                        // validate if subscription-auth mode is configured
-                        switch (policies.get().subscription_auth_mode) {
-                        case Prefix:
-                            if (!subscription.startsWith(role)) {
-                                PulsarServerException ex = new PulsarServerException(String.format(
-                                        "Failed to create consumer - The subscription name needs to be prefixed by the "
-                                                + "authentication role, like %s-xxxx for topic: %s", role, topicName));
-                                permissionFuture.completeExceptionally(ex);
-                                return;
+                            // validate if subscription-auth mode is configured
+                            switch (policies.get().subscription_auth_mode) {

Review comment:
       yes, I will check before this.
   Thanks @eolivelli  




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] Technoboy- commented on pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
Technoboy- commented on pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#issuecomment-1074744048


   > @Technoboy- I notice that no tests to cover the PulsarAuthorizationProvider, could you add some tests for this?
   
   Integration test has coverage this.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] zymap commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
zymap commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r833890936



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -231,185 +197,149 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     private CompletableFuture<Boolean> allowConsumeOrProduceOpsAsync(NamespaceName namespaceName,
                                                                      String role,
                                                                      AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<>();
-        allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
-                .whenComplete((consumeAuthorized, e) -> {
-                    if (e == null) {
-                        if (consumeAuthorized) {
-                            finalResult.complete(consumeAuthorized);
-                            return;
-                        }
-                    } else {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Namespace [{}] Role [{}] exception occurred while trying to check Consume "
-                                    + "permission. {}", namespaceName, role, e.getCause());
-                        }
+        return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
+                .thenCompose(canConsumer -> {
+                    if (canConsumer) {
+                        return CompletableFuture.completedFuture(true);
                     }
-                    allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce)
-                            .whenComplete((produceAuthorized, ex) -> {
-                                if (ex == null) {
-                                    finalResult.complete(produceAuthorized);
-                                } else {
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Namespace [{}] Role [{}] exception occurred while trying to check "
-                                                + "Produce permission. {}", namespaceName, role, ex.getCause());
-                                    }
-                                    finalResult.completeExceptionally(ex.getCause());
-                                }
-                            });
+                    return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce);
                 });
-
-        return finalResult;
     }
 
     private CompletableFuture<Boolean> allowTheSpecifiedActionOpsAsync(NamespaceName namespaceName, String role,
                                                                        AuthenticationDataSource authenticationData,
                                                                        AuthAction authAction) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
-                    }
-                } else {
-                    Map<String, Set<AuthAction>> namespaceRoles = policies.get()
-                            .auth_policies.getNamespaceAuthentication();
-                    Set<AuthAction> namespaceActions = namespaceRoles.get(role);
-                    if (namespaceActions != null && namespaceActions.contains(authAction)) {
-                        // The role has namespace level permission
-                        permissionFuture.complete(true);
-                        return;
-                    }
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenApply(policies -> {
+            if (!policies.isPresent()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
+                }
+            } else {
+                Map<String, Set<AuthAction>> namespaceRoles = policies.get()
+                        .auth_policies.getNamespaceAuthentication();
+                Set<AuthAction> namespaceActions = namespaceRoles.get(role);
+                if (namespaceActions != null && namespaceActions.contains(authAction)) {
+                    // The role has namespace level permission
+                    return true;
+                }
 
-                    // Using wildcard
-                    if (conf.isAuthorizationAllowWildcardsMatching()) {
-                        if (checkWildcardPermission(role, authAction, namespaceRoles)) {
-                            // The role has namespace level permission by wildcard match
-                            permissionFuture.complete(true);
-                            return;
-                        }
+                // Using wildcard
+                if (conf.isAuthorizationAllowWildcardsMatching()) {
+                    if (checkWildcardPermission(role, authAction, namespaceRoles)) {
+                        // The role has namespace level permission by wildcard match
+                        return true;
                     }
                 }
-                permissionFuture.complete(false);
-            }).exceptionally(ex -> {
-                log.warn("Client  with Role - {} failed to get permissions for namespace - {}. {}", role, namespaceName,
-                        ex.getMessage());
-                permissionFuture.completeExceptionally(ex);
-                return null;
-            });
-        } catch (Exception e) {
-            log.warn("Client  with Role - {} failed to get permissions for namespace - {}. {}", role, namespaceName,
-                    e.getMessage());
-            permissionFuture.completeExceptionally(e);
-        }
-        return permissionFuture;
+            }
+            return false;
+        });
     }
 
     @Override
     public CompletableFuture<Void> grantPermissionAsync(TopicName topicName, Set<AuthAction> actions,
-            String role, String authDataJson) {
-        try {
-            validatePoliciesReadOnlyAccess();
-        } catch (Exception e) {
-            return FutureUtil.failedFuture(e);
-        }
+                                                        String role, String authDataJson) {
 
-        String topicUri = topicName.toString();
-        return pulsarResources.getNamespaceResources()
-                .setPoliciesAsync(topicName.getNamespaceObject(), policies -> {
-                    policies.auth_policies.getTopicAuthentication()
-                            .computeIfAbsent(topicUri, __ -> new HashMap<>())
-                            .put(role, actions);
-                    return policies;
-                }).whenComplete((__, throwable) -> {
-                    if (throwable != null) {
-                        log.error("[{}] Failed to set permissions for role {} on topic {}", role, role, topicName,
-                                throwable);
-                    } else {
-                        log.info("[{}] Successfully granted access for role {}: {} - topic {}", role, role, actions,
-                                topicUri);
-                    }
-                });
+        return getPoliciesReadOnlyAsync().thenCompose(readonly -> {
+            if (readonly) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies are read-only. Broker cannot do read-write operations");
+                }
+                throw new IllegalStateException("policies are in readonly mode");
+            }
+            String topicUri = topicName.toString();
+            return pulsarResources.getNamespaceResources()
+                    .setPoliciesAsync(topicName.getNamespaceObject(), policies -> {
+                        policies.auth_policies.getTopicAuthentication()
+                                .computeIfAbsent(topicUri, __ -> new HashMap<>())
+                                .put(role, actions);
+                        return policies;
+                    }).whenComplete((__, ex) -> {
+                        if (ex != null) {
+                            log.error("Failed to set permissions for role {} on topic {}", role, topicName, ex);
+                        } else {
+                            log.info("Successfully granted access for role {}: {} - topic {}", role, actions, topicUri);
+                        }
+                    });
+        });
     }
 
     @Override
     public CompletableFuture<Void> grantPermissionAsync(NamespaceName namespaceName, Set<AuthAction> actions,
-            String role, String authDataJson) {
-        try {
-            validatePoliciesReadOnlyAccess();
-        } catch (Exception e) {
-            return FutureUtil.failedFuture(e);
-        }
-
-        return pulsarResources.getNamespaceResources()
-                .setPoliciesAsync(namespaceName, policies -> {
-                    policies.auth_policies.getNamespaceAuthentication().put(role, actions);
-                    return policies;
-                }).whenComplete((__, throwable) -> {
-                    if (throwable != null) {
-                        log.error("[{}] Failed to set permissions for role {} namespace {}", role, role, namespaceName,
-                                throwable);
-                    } else {
-                        log.info("[{}] Successfully granted access for role {}: {} - namespace {}", role, role, actions,
-                                namespaceName);
-                    }
-                });
+                                                        String role, String authDataJson) {
+        return getPoliciesReadOnlyAsync().thenCompose(readonly -> {
+            if (readonly) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies are read-only. Broker cannot do read-write operations");
+                }
+                throw new IllegalStateException("policies are in readonly mode");

Review comment:
       If no one catches the exception, the future will never be complete. For example:
   
   ```
           CompletableFuture future = new CompletableFuture();
           future.thenRun(() -> {
               System.out.println("first thing");
           }).thenCompose(b -> {
               throw new IllegalArgumentException("fail future");
           }).thenRun(() -> {
               System.out.println("other things");
           });
           future.get();
   ```
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] zymap commented on a change in pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
zymap commented on a change in pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747#discussion_r833890936



##########
File path: pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java
##########
@@ -231,185 +197,149 @@ public void initialize(ServiceConfiguration conf, PulsarResources pulsarResource
     private CompletableFuture<Boolean> allowConsumeOrProduceOpsAsync(NamespaceName namespaceName,
                                                                      String role,
                                                                      AuthenticationDataSource authenticationData) {
-        CompletableFuture<Boolean> finalResult = new CompletableFuture<>();
-        allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
-                .whenComplete((consumeAuthorized, e) -> {
-                    if (e == null) {
-                        if (consumeAuthorized) {
-                            finalResult.complete(consumeAuthorized);
-                            return;
-                        }
-                    } else {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Namespace [{}] Role [{}] exception occurred while trying to check Consume "
-                                    + "permission. {}", namespaceName, role, e.getCause());
-                        }
+        return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.consume)
+                .thenCompose(canConsumer -> {
+                    if (canConsumer) {
+                        return CompletableFuture.completedFuture(true);
                     }
-                    allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce)
-                            .whenComplete((produceAuthorized, ex) -> {
-                                if (ex == null) {
-                                    finalResult.complete(produceAuthorized);
-                                } else {
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Namespace [{}] Role [{}] exception occurred while trying to check "
-                                                + "Produce permission. {}", namespaceName, role, ex.getCause());
-                                    }
-                                    finalResult.completeExceptionally(ex.getCause());
-                                }
-                            });
+                    return allowTheSpecifiedActionOpsAsync(namespaceName, role, authenticationData, AuthAction.produce);
                 });
-
-        return finalResult;
     }
 
     private CompletableFuture<Boolean> allowTheSpecifiedActionOpsAsync(NamespaceName namespaceName, String role,
                                                                        AuthenticationDataSource authenticationData,
                                                                        AuthAction authAction) {
-        CompletableFuture<Boolean> permissionFuture = new CompletableFuture<>();
-        try {
-            pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenAccept(policies -> {
-                if (!policies.isPresent()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
-                    }
-                } else {
-                    Map<String, Set<AuthAction>> namespaceRoles = policies.get()
-                            .auth_policies.getNamespaceAuthentication();
-                    Set<AuthAction> namespaceActions = namespaceRoles.get(role);
-                    if (namespaceActions != null && namespaceActions.contains(authAction)) {
-                        // The role has namespace level permission
-                        permissionFuture.complete(true);
-                        return;
-                    }
+        return pulsarResources.getNamespaceResources().getPoliciesAsync(namespaceName).thenApply(policies -> {
+            if (!policies.isPresent()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies node couldn't be found for namespace : {}", namespaceName);
+                }
+            } else {
+                Map<String, Set<AuthAction>> namespaceRoles = policies.get()
+                        .auth_policies.getNamespaceAuthentication();
+                Set<AuthAction> namespaceActions = namespaceRoles.get(role);
+                if (namespaceActions != null && namespaceActions.contains(authAction)) {
+                    // The role has namespace level permission
+                    return true;
+                }
 
-                    // Using wildcard
-                    if (conf.isAuthorizationAllowWildcardsMatching()) {
-                        if (checkWildcardPermission(role, authAction, namespaceRoles)) {
-                            // The role has namespace level permission by wildcard match
-                            permissionFuture.complete(true);
-                            return;
-                        }
+                // Using wildcard
+                if (conf.isAuthorizationAllowWildcardsMatching()) {
+                    if (checkWildcardPermission(role, authAction, namespaceRoles)) {
+                        // The role has namespace level permission by wildcard match
+                        return true;
                     }
                 }
-                permissionFuture.complete(false);
-            }).exceptionally(ex -> {
-                log.warn("Client  with Role - {} failed to get permissions for namespace - {}. {}", role, namespaceName,
-                        ex.getMessage());
-                permissionFuture.completeExceptionally(ex);
-                return null;
-            });
-        } catch (Exception e) {
-            log.warn("Client  with Role - {} failed to get permissions for namespace - {}. {}", role, namespaceName,
-                    e.getMessage());
-            permissionFuture.completeExceptionally(e);
-        }
-        return permissionFuture;
+            }
+            return false;
+        });
     }
 
     @Override
     public CompletableFuture<Void> grantPermissionAsync(TopicName topicName, Set<AuthAction> actions,
-            String role, String authDataJson) {
-        try {
-            validatePoliciesReadOnlyAccess();
-        } catch (Exception e) {
-            return FutureUtil.failedFuture(e);
-        }
+                                                        String role, String authDataJson) {
 
-        String topicUri = topicName.toString();
-        return pulsarResources.getNamespaceResources()
-                .setPoliciesAsync(topicName.getNamespaceObject(), policies -> {
-                    policies.auth_policies.getTopicAuthentication()
-                            .computeIfAbsent(topicUri, __ -> new HashMap<>())
-                            .put(role, actions);
-                    return policies;
-                }).whenComplete((__, throwable) -> {
-                    if (throwable != null) {
-                        log.error("[{}] Failed to set permissions for role {} on topic {}", role, role, topicName,
-                                throwable);
-                    } else {
-                        log.info("[{}] Successfully granted access for role {}: {} - topic {}", role, role, actions,
-                                topicUri);
-                    }
-                });
+        return getPoliciesReadOnlyAsync().thenCompose(readonly -> {
+            if (readonly) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies are read-only. Broker cannot do read-write operations");
+                }
+                throw new IllegalStateException("policies are in readonly mode");
+            }
+            String topicUri = topicName.toString();
+            return pulsarResources.getNamespaceResources()
+                    .setPoliciesAsync(topicName.getNamespaceObject(), policies -> {
+                        policies.auth_policies.getTopicAuthentication()
+                                .computeIfAbsent(topicUri, __ -> new HashMap<>())
+                                .put(role, actions);
+                        return policies;
+                    }).whenComplete((__, ex) -> {
+                        if (ex != null) {
+                            log.error("Failed to set permissions for role {} on topic {}", role, topicName, ex);
+                        } else {
+                            log.info("Successfully granted access for role {}: {} - topic {}", role, actions, topicUri);
+                        }
+                    });
+        });
     }
 
     @Override
     public CompletableFuture<Void> grantPermissionAsync(NamespaceName namespaceName, Set<AuthAction> actions,
-            String role, String authDataJson) {
-        try {
-            validatePoliciesReadOnlyAccess();
-        } catch (Exception e) {
-            return FutureUtil.failedFuture(e);
-        }
-
-        return pulsarResources.getNamespaceResources()
-                .setPoliciesAsync(namespaceName, policies -> {
-                    policies.auth_policies.getNamespaceAuthentication().put(role, actions);
-                    return policies;
-                }).whenComplete((__, throwable) -> {
-                    if (throwable != null) {
-                        log.error("[{}] Failed to set permissions for role {} namespace {}", role, role, namespaceName,
-                                throwable);
-                    } else {
-                        log.info("[{}] Successfully granted access for role {}: {} - namespace {}", role, role, actions,
-                                namespaceName);
-                    }
-                });
+                                                        String role, String authDataJson) {
+        return getPoliciesReadOnlyAsync().thenCompose(readonly -> {
+            if (readonly) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Policies are read-only. Broker cannot do read-write operations");
+                }
+                throw new IllegalStateException("policies are in readonly mode");

Review comment:
       If no one catches the exception, the future will never be completed. For example:
   
   ```
           CompletableFuture future = new CompletableFuture();
           future.thenRun(() -> {
               System.out.println("first thing");
           }).thenCompose(b -> {
               throw new IllegalArgumentException("fail future");
           }).thenRun(() -> {
               System.out.println("other things");
           });
           future.get();
   ```
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [pulsar] Technoboy- merged pull request #14747: [cleanup][broker]: Refactor PulsarAuthorizationProvider.

Posted by GitBox <gi...@apache.org>.
Technoboy- merged pull request #14747:
URL: https://github.com/apache/pulsar/pull/14747


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org