Skip to content

Commit c598974

Browse files
authored
[improve][PIP] PIP-383: Support granting/revoking permissions for multiple topics (#23355)
1 parent 06fc259 commit c598974

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

pip/pip-383.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# PIP-383: Support granting/revoking permissions for multiple topics
2+
3+
## Background
4+
5+
In AuthorizationProvider, the authorization interface `grantPermissionAsync(TopicName topicName, Set<AuthAction> actions, String role, String authDataJson)` currently only supports granting permissions to a single topic at a time.
6+
When multiple topics need to be authorized under a namespace, the client makes the calls to the authorization interface concurrently.
7+
Since the permissions information is stored in the namespace-level policies, and multiple topics may be on different brokers, concurrent authorization modification will cause concurrent modification exceptions.
8+
Therefore, supporting granting permissions for multiple topics is very beneficial.
9+
10+
11+
## Motivation
12+
13+
Supporting granting/revoking permissions for multiple topics,
14+
add `grantPermissionAsync(List<GrantTopicPermissionOptions> options)` and `revokePermissionAsync(List<RevokeTopicPermissionOptions> options)` in AuthorizationProvider.
15+
16+
## Goals
17+
18+
### In Scope
19+
20+
- Add `grantPermissionAsync(List<GrantTopicPermissionOptions> options)` in AuthorizationProvider.
21+
- Add `revokePermissionAsync(List<GrantTopicPermissionOptions> options)` in AuthorizationProvider.
22+
23+
## High-Level Design
24+
25+
### Design & Implementation Details
26+
27+
Add default method implementation in AuthorizationProvider
28+
```java
29+
30+
public interface AuthorizationProvider extends Closeable {
31+
32+
default CompletableFuture<Void> grantPermissionAsync(List<GrantTopicPermissionOptions> options) {
33+
return FutureUtil.failedFuture(new IllegalStateException(
34+
String.format("grantPermissionAsync is not supported by the Authorization")));
35+
}
36+
37+
default CompletableFuture<Void> revokePermissionAsync(List<RevokeTopicPermissionOptions> options) {
38+
return FutureUtil.failedFuture(new IllegalStateException(
39+
String.format("revokePermissionAsync is not supported by the Authorization")));
40+
}
41+
}
42+
```
43+
44+
```
45+
@Data
46+
@Builder
47+
public class GrantTopicPermissionOptions {
48+
49+
private final String topic;
50+
51+
private final String role;
52+
53+
private final Set<AuthAction> actions;
54+
}
55+
56+
@Data
57+
@Builder
58+
public class RevokeTopicPermissionOptions {
59+
60+
private final String topic;
61+
62+
private final String role;
63+
}
64+
```
65+
66+
Add namespace admin API.
67+
68+
```java
69+
public interface Namespaces {
70+
71+
CompletableFuture<Void> grantPermissionOnTopicsAsync(List<GrantTopicPermissionOptions> options);
72+
73+
void grantPermissionOnTopics(List<GrantTopicPermissionOptions> options) throws PulsarAdminException;
74+
75+
CompletableFuture<Void> revokePermissionOnTopicsAsync(List<RevokeTopicPermissionOptions> options);
76+
77+
void revokePermissionOnTopics(List<RevokeTopicPermissionOptions> options) throws PulsarAdminException;
78+
}
79+
```
80+
81+
Add namespace rest implementation in broker side.
82+
```java
83+
@POST
84+
@Path("/grantPermissions")
85+
public void grantPermissionOnTopics(@Suspended final AsyncResponse asyncResponse,
86+
List<GrantTopicPermissionOptions> options) {
87+
internalGrantPermissionsAsync(options)
88+
.thenAccept(__ -> asyncResponse.resume(Response.noContent().build()))
89+
.exceptionally(ex -> {
90+
log.error("[{}] Failed to grant permissions {}",
91+
clientAppId(), options, ex);
92+
resumeAsyncResponseExceptionally(asyncResponse, ex);
93+
return null;
94+
});
95+
}
96+
97+
@POST
98+
@Path("/revokePermissions")
99+
public void revokePermissionOnTopics(@Suspended final AsyncResponse asyncResponse,
100+
List<RevokeTopicPermissionOptions> options) {
101+
internalRevokePermissionsAsync(options)
102+
.thenAccept(__ -> asyncResponse.resume(Response.noContent().build()))
103+
.exceptionally(ex -> {
104+
log.error("[{}] Failed to revoke permissions {}",
105+
clientAppId(), options, ex);
106+
resumeAsyncResponseExceptionally(asyncResponse, ex);
107+
return null;
108+
});
109+
}
110+
```
111+
112+
so user can grant/revoke permissions to multi-topics like :
113+
```java
114+
public class TestAuthorization {
115+
116+
@Test
117+
public void testGrantPermission() {
118+
// grant permission for multi-topics
119+
List<GrantPermissionOptions> grantPermissions = new ArrayList<>();
120+
grantPermissions.add(GrantPermissionOptions.builder().topic("topic1").role("role1").actions(Set.of(AuthAction.produce)).build());
121+
grantPermissions.add(GrantPermissionOptions.builder().topic("topic2").role("role2").actions(Set.of(AuthAction.consume)).build());
122+
admin.namespaces().grantPermissionOnTopics(grantPermissions);
123+
// revoke permission topics
124+
List<RevokePermissionOptions> revokePermissions = new ArrayList<>();
125+
revokePermissions.add(RevokePermissionOptions.builder().topic("topic1").role("role1").build());
126+
revokePermissions.add(RevokePermissionOptions.builder().topic("topic2").role("role2").build());
127+
admin.namespaces().revokePermissionOnTopics(revokePermissions);
128+
}
129+
}
130+
131+
```
132+
133+
## Backward & Forward Compatibility
134+
135+
136+
137+
## Alternatives
138+
139+
## General Notes
140+
141+
## Links
142+
143+
* Mailing List discussion thread: https://lists.apache.org/thread/6n2jdl9bsf1f6xz2orygz3kvxmy11ykh
144+
* Mailing List voting thread: https://lists.apache.org/thread/qbyvs75r0d64h6jk8w1swr782l85b77h

0 commit comments

Comments
 (0)