-
Notifications
You must be signed in to change notification settings - Fork 3.7k
[improve][authorization] Uniformly use allowTopicOperationAsync to check permissions #19461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -105,9 +105,15 @@ default void initialize(ServiceConfiguration conf, PulsarResources pulsarResourc | |
| * the fully qualified topic name associated with the topic. | ||
| * @param role | ||
| * the app id used to send messages to the topic. | ||
| * | ||
| * @deprecated | ||
| * Use {@link #allowTopicOperationAsync(TopicName, String, TopicOperation, AuthenticationDataSource)} instead. | ||
| */ | ||
| CompletableFuture<Boolean> canProduceAsync(TopicName topicName, String role, | ||
| AuthenticationDataSource authenticationData); | ||
| @Deprecated | ||
| default CompletableFuture<Boolean> canProduceAsync(TopicName topicName, String role, | ||
| AuthenticationDataSource authenticationData) { | ||
| return CompletableFuture.completedFuture(false); | ||
| } | ||
|
|
||
| /** | ||
| * Check if the specified role has permission to receive messages from the specified fully qualified topic name. | ||
|
|
@@ -118,9 +124,16 @@ CompletableFuture<Boolean> canProduceAsync(TopicName topicName, String role, | |
| * the app id used to receive messages from the topic. | ||
| * @param subscription | ||
| * the subscription name defined by the client | ||
| * | ||
| * @deprecated | ||
| * Use {@link #allowTopicOperationAsync(TopicName, String, TopicOperation, AuthenticationDataSource)} instead. | ||
| */ | ||
| CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role, | ||
| AuthenticationDataSource authenticationData, String subscription); | ||
| @Deprecated | ||
| default CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role, | ||
| AuthenticationDataSource authenticationData, | ||
| String subscription) { | ||
| return CompletableFuture.completedFuture(false); | ||
| } | ||
|
|
||
| /** | ||
| * Check whether the specified role can perform a lookup for the specified topic. | ||
|
|
@@ -129,11 +142,15 @@ CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String role, | |
| * | ||
| * @param topicName | ||
| * @param role | ||
| * @return | ||
| * @throws Exception | ||
| * | ||
| * @deprecated | ||
| * Use {@link #allowTopicOperationAsync(TopicName, String, TopicOperation, AuthenticationDataSource)} instead. | ||
| */ | ||
| CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role, | ||
| AuthenticationDataSource authenticationData); | ||
| @Deprecated | ||
| default CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String role, | ||
| AuthenticationDataSource authenticationData) { | ||
| return CompletableFuture.completedFuture(false); | ||
| } | ||
|
|
||
| /** | ||
| * Allow all function operations with in this namespace. | ||
|
|
@@ -345,9 +362,41 @@ default CompletableFuture<Boolean> allowTopicOperationAsync(TopicName topic, | |
| String role, | ||
| TopicOperation operation, | ||
| AuthenticationDataSource authData) { | ||
| return FutureUtil.failedFuture( | ||
| new IllegalStateException("TopicOperation [" + operation.name() + "] is not supported by the Authorization" | ||
| + "provider you are using.")); | ||
|
Comment on lines
-348
to
-350
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you able to explain a bit more why this is required for backwards compatibility? I think we should be able to leave this here and leave the |
||
| switch (operation) { | ||
| case LOOKUP: | ||
| case GET_STATS: | ||
| case GET_METADATA: | ||
| return canLookupAsync(topic, role, authData); | ||
| case PRODUCE: | ||
| return canProduceAsync(topic, role, authData); | ||
| case GET_SUBSCRIPTIONS: | ||
| case CONSUME: | ||
| case SUBSCRIBE: | ||
| case UNSUBSCRIBE: | ||
| case SKIP: | ||
| case EXPIRE_MESSAGES: | ||
| case PEEK_MESSAGES: | ||
| case RESET_CURSOR: | ||
| case GET_BACKLOG_SIZE: | ||
| case SET_REPLICATED_SUBSCRIPTION_STATUS: | ||
| case GET_REPLICATED_SUBSCRIPTION_STATUS: | ||
| return canConsumeAsync(topic, role, authData, authData.getSubscription()); | ||
| case TERMINATE: | ||
| case COMPACT: | ||
| case OFFLOAD: | ||
| case UNLOAD: | ||
| case DELETE_METADATA: | ||
| case UPDATE_METADATA: | ||
| case ADD_BUNDLE_RANGE: | ||
| case GET_BUNDLE_RANGE: | ||
| case DELETE_BUNDLE_RANGE: | ||
| return CompletableFuture.completedFuture(false); | ||
| default: | ||
| return FutureUtil.failedFuture( | ||
| new IllegalStateException( | ||
| "TopicOperation [" + operation.name() + "] is not supported by the Authorization" | ||
| + "provider you are using.")); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |
| import org.apache.pulsar.broker.PulsarServerException; | ||
| import org.apache.pulsar.broker.ServiceConfiguration; | ||
| import org.apache.pulsar.broker.authentication.AuthenticationDataSource; | ||
| import org.apache.pulsar.broker.authentication.AuthenticationDataSubscription; | ||
| import org.apache.pulsar.broker.resources.PulsarResources; | ||
| import org.apache.pulsar.common.naming.NamespaceName; | ||
| import org.apache.pulsar.common.naming.TopicName; | ||
|
|
@@ -166,7 +167,7 @@ public CompletableFuture<Boolean> canProduceAsync(TopicName topicName, String ro | |
| if (isSuperUser) { | ||
| return CompletableFuture.completedFuture(true); | ||
| } else { | ||
| return provider.canProduceAsync(topicName, role, authenticationData); | ||
| return provider.allowTopicOperationAsync(topicName, role, TopicOperation.PRODUCE, authenticationData); | ||
| } | ||
| }); | ||
| } | ||
|
|
@@ -191,7 +192,14 @@ public CompletableFuture<Boolean> canConsumeAsync(TopicName topicName, String ro | |
| if (isSuperUser) { | ||
| return CompletableFuture.completedFuture(true); | ||
| } else { | ||
| return provider.canConsumeAsync(topicName, role, authenticationData, subscription); | ||
| AuthenticationDataSource subscriptionDataSource; | ||
| if (authenticationData instanceof AuthenticationDataSubscription) { | ||
| subscriptionDataSource = authenticationData; | ||
| } else { | ||
| subscriptionDataSource = new AuthenticationDataSubscription(authenticationData, subscription); | ||
| } | ||
| return provider.allowTopicOperationAsync(topicName, role, TopicOperation.CONSUME, | ||
| subscriptionDataSource); | ||
|
Comment on lines
-194
to
+202
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we deprecate this |
||
| } | ||
| }); | ||
| } | ||
|
|
@@ -273,7 +281,7 @@ public CompletableFuture<Boolean> canLookupAsync(TopicName topicName, String rol | |
| if (isSuperUser) { | ||
| return CompletableFuture.completedFuture(true); | ||
| } else { | ||
| return provider.canLookupAsync(topicName, role, authenticationData); | ||
| return provider.allowTopicOperationAsync(topicName, role, TopicOperation.LOOKUP, authenticationData); | ||
|
Comment on lines
281
to
+284
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only tangentially related to your PR, but it seems like a broken abstraction that the My goal is to move that logic into the provider so that plugin implementations do not need to deal with the complexity of when to check for super user and when not to. All of this logic should be delegated to the provider, in my opinion. That change is probably worth its own PR, though. |
||
| } | ||
| }); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of providing a default implementation, I think we should just deprecate these methods. Then, in the
PulsarAuthorizationProviderclass, we can remove the@Overrideannotation and those methods become internal implementation details instead of top level methods on the interface.