Skip to content

Commit f868570

Browse files
committed
rbac enabled tests
1 parent e369e62 commit f868570

File tree

3 files changed

+393
-169
lines changed

3 files changed

+393
-169
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
package io.kafbat.ui.service.rbac;
2+
3+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.ADMIN_ROLE;
4+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.CONNECT_NAME;
5+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.CONSUMER_GROUP_NAME;
6+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.DEV_CLUSTER;
7+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.DEV_ROLE;
8+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.PROD_CLUSTER;
9+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.SCHEMA_NAME;
10+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.TOPIC_NAME;
11+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.getAccessContext;
12+
import static org.mockito.Mockito.mock;
13+
import static org.mockito.Mockito.when;
14+
15+
import io.kafbat.ui.AbstractIntegrationTest;
16+
import io.kafbat.ui.config.auth.RbacUser;
17+
import io.kafbat.ui.config.auth.RoleBasedAccessControlProperties;
18+
import io.kafbat.ui.model.ClusterDTO;
19+
import io.kafbat.ui.model.ConnectDTO;
20+
import io.kafbat.ui.model.InternalTopic;
21+
import io.kafbat.ui.model.rbac.AccessContext;
22+
import io.kafbat.ui.model.rbac.Role;
23+
import java.util.List;
24+
import org.junit.jupiter.api.BeforeEach;
25+
import org.junit.jupiter.api.Test;
26+
import org.mockito.Mock;
27+
import org.mockito.MockedStatic;
28+
import org.mockito.Mockito;
29+
import org.springframework.beans.factory.annotation.Autowired;
30+
import org.springframework.security.access.AccessDeniedException;
31+
import org.springframework.security.core.Authentication;
32+
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
33+
import org.springframework.security.core.context.SecurityContext;
34+
import org.springframework.test.util.ReflectionTestUtils;
35+
import reactor.core.publisher.Mono;
36+
import reactor.test.StepVerifier;
37+
38+
/**
39+
* Test cases for AccessControlService when RBAC is enabled.
40+
*/
41+
class AccessControlServiceRbacEnabledTest extends AbstractIntegrationTest {
42+
43+
@Autowired
44+
AccessControlService accessControlService;
45+
46+
@Mock
47+
SecurityContext securityContext;
48+
49+
@Mock
50+
Authentication authentication;
51+
52+
@Mock
53+
RbacUser user;
54+
55+
@BeforeEach
56+
void setUp() {
57+
// Mock roles
58+
List<Role> roles = List.of(
59+
MockedRbacUtils.getAdminRole(),
60+
MockedRbacUtils.getDevRole()
61+
);
62+
RoleBasedAccessControlProperties properties = mock();
63+
when(properties.getRoles()).thenReturn(roles);
64+
65+
ReflectionTestUtils.setField(accessControlService, "properties", properties);
66+
ReflectionTestUtils.setField(accessControlService, "rbacEnabled", true);
67+
68+
// Mock security context
69+
when(securityContext.getAuthentication()).thenReturn(authentication);
70+
when(authentication.getPrincipal()).thenReturn(user);
71+
}
72+
73+
public void withSecurityContext(Runnable runnable) {
74+
try (MockedStatic<ReactiveSecurityContextHolder> ctxHolder = Mockito.mockStatic(
75+
ReactiveSecurityContextHolder.class)) {
76+
// Mock static method to get security context
77+
ctxHolder.when(ReactiveSecurityContextHolder::getContext).thenReturn(Mono.just(securityContext));
78+
runnable.run();
79+
}
80+
}
81+
82+
@Test
83+
void validateAccess() {
84+
withSecurityContext(() -> {
85+
when(user.groups()).thenReturn(List.of(ADMIN_ROLE));
86+
AccessContext context = getAccessContext(PROD_CLUSTER, true);
87+
Mono<Void> validateAccessMono = accessControlService.validateAccess(context);
88+
StepVerifier.create(validateAccessMono)
89+
.expectComplete()
90+
.verify();
91+
});
92+
}
93+
94+
@Test
95+
void validateAccess_deniedCluster() {
96+
withSecurityContext(() -> {
97+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
98+
AccessContext context = getAccessContext(PROD_CLUSTER, true);
99+
Mono<Void> validateAccessMono = accessControlService.validateAccess(context);
100+
StepVerifier.create(validateAccessMono)
101+
.expectErrorMatches(e -> e instanceof AccessDeniedException)
102+
.verify();
103+
});
104+
}
105+
106+
@Test
107+
void validateAccess_deniedResourceNotAccessible() {
108+
withSecurityContext(() -> {
109+
when(user.groups()).thenReturn(List.of(ADMIN_ROLE));
110+
AccessContext context = getAccessContext(PROD_CLUSTER, false);
111+
Mono<Void> validateAccessMono = accessControlService.validateAccess(context);
112+
StepVerifier.create(validateAccessMono)
113+
.expectErrorMatches(e -> e instanceof AccessDeniedException)
114+
.verify();
115+
});
116+
}
117+
118+
@Test
119+
void isClusterAccessible() {
120+
withSecurityContext(() -> {
121+
when(user.groups()).thenReturn(List.of(ADMIN_ROLE));
122+
ClusterDTO clusterDto = new ClusterDTO();
123+
clusterDto.setName(PROD_CLUSTER);
124+
Mono<Boolean> clusterAccessibleMono = accessControlService.isClusterAccessible(clusterDto);
125+
StepVerifier.create(clusterAccessibleMono)
126+
.expectNext(true)
127+
.expectComplete()
128+
.verify();
129+
});
130+
}
131+
132+
@Test
133+
void isClusterAccessible_deniedCluster() {
134+
withSecurityContext(() -> {
135+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
136+
ClusterDTO clusterDto = new ClusterDTO();
137+
clusterDto.setName(PROD_CLUSTER);
138+
Mono<Boolean> clusterAccessibleMono = accessControlService.isClusterAccessible(clusterDto);
139+
StepVerifier.create(clusterAccessibleMono)
140+
.expectNext(false)
141+
.expectComplete()
142+
.verify();
143+
});
144+
}
145+
146+
@Test
147+
void filterViewableTopics() {
148+
withSecurityContext(() -> {
149+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
150+
ClusterDTO clusterDto = new ClusterDTO();
151+
clusterDto.setName(DEV_CLUSTER);
152+
List<InternalTopic> topics = List.of(
153+
InternalTopic.builder()
154+
.name(TOPIC_NAME)
155+
.build()
156+
);
157+
Mono<List<InternalTopic>> filterTopicsMono = accessControlService.filterViewableTopics(topics, DEV_CLUSTER);
158+
StepVerifier.create(filterTopicsMono)
159+
.expectNextMatches(responseTopics -> responseTopics.stream().anyMatch(t -> t.getName().equals(TOPIC_NAME)))
160+
.expectComplete()
161+
.verify();
162+
});
163+
}
164+
165+
@Test
166+
void filterViewableTopics_notAccessibleTopic() {
167+
withSecurityContext(() -> {
168+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
169+
ClusterDTO clusterDto = new ClusterDTO();
170+
clusterDto.setName(DEV_CLUSTER);
171+
List<InternalTopic> topics = List.of(
172+
InternalTopic.builder()
173+
.name("some other topic")
174+
.build()
175+
);
176+
Mono<List<InternalTopic>> filterTopicsMono = accessControlService.filterViewableTopics(topics, DEV_CLUSTER);
177+
StepVerifier.create(filterTopicsMono)
178+
.expectNextMatches(List::isEmpty)
179+
.expectComplete()
180+
.verify();
181+
});
182+
}
183+
184+
@Test
185+
void isConsumerGroupAccessible() {
186+
withSecurityContext(() -> {
187+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
188+
Mono<Boolean> consumerGroupAccessibleMono =
189+
accessControlService.isConsumerGroupAccessible(CONSUMER_GROUP_NAME, DEV_CLUSTER);
190+
StepVerifier.create(consumerGroupAccessibleMono)
191+
.expectNext(true)
192+
.expectComplete()
193+
.verify();
194+
});
195+
}
196+
197+
@Test
198+
void isConsumerGroupAccessible_notAccessible() {
199+
withSecurityContext(() -> {
200+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
201+
Mono<Boolean> consumerGroupAccessibleMono =
202+
accessControlService.isConsumerGroupAccessible("SOME OTHER CONSUMER", DEV_CLUSTER);
203+
StepVerifier.create(consumerGroupAccessibleMono)
204+
.expectNext(false)
205+
.expectComplete()
206+
.verify();
207+
});
208+
}
209+
210+
@Test
211+
void isSchemaAccessible() {
212+
withSecurityContext(() -> {
213+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
214+
Mono<Boolean> consumerGroupAccessibleMono =
215+
accessControlService.isSchemaAccessible(SCHEMA_NAME, DEV_CLUSTER);
216+
StepVerifier.create(consumerGroupAccessibleMono)
217+
.expectNext(true)
218+
.expectComplete()
219+
.verify();
220+
});
221+
}
222+
223+
@Test
224+
void isSchemaAccessible_notAccessible() {
225+
withSecurityContext(() -> {
226+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
227+
Mono<Boolean> consumerGroupAccessibleMono =
228+
accessControlService.isSchemaAccessible("SOME OTHER SCHEMA", DEV_CLUSTER);
229+
StepVerifier.create(consumerGroupAccessibleMono)
230+
.expectNext(false)
231+
.expectComplete()
232+
.verify();
233+
});
234+
}
235+
236+
@Test
237+
void isConnectAccessible() {
238+
withSecurityContext(() -> {
239+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
240+
Mono<Boolean> consumerGroupAccessibleMono =
241+
accessControlService.isConnectAccessible(CONNECT_NAME, DEV_CLUSTER);
242+
StepVerifier.create(consumerGroupAccessibleMono)
243+
.expectNext(true)
244+
.expectComplete()
245+
.verify();
246+
});
247+
}
248+
249+
@Test
250+
void isConnectAccessible_notAccessible() {
251+
withSecurityContext(() -> {
252+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
253+
Mono<Boolean> consumerGroupAccessibleMono =
254+
accessControlService.isConnectAccessible("SOME OTHER CONNECT", DEV_CLUSTER);
255+
StepVerifier.create(consumerGroupAccessibleMono)
256+
.expectNext(false)
257+
.expectComplete()
258+
.verify();
259+
});
260+
}
261+
262+
@Test
263+
void isConnectAccessibleDto() {
264+
withSecurityContext(() -> {
265+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
266+
ConnectDTO connectDto = ConnectDTO.builder()
267+
.name(CONNECT_NAME)
268+
.build();
269+
Mono<Boolean> consumerGroupAccessibleMono =
270+
accessControlService.isConnectAccessible(connectDto, DEV_CLUSTER);
271+
StepVerifier.create(consumerGroupAccessibleMono)
272+
.expectNext(true)
273+
.expectComplete()
274+
.verify();
275+
});
276+
}
277+
278+
@Test
279+
void isConnectAccessibleDto_notAccessible() {
280+
withSecurityContext(() -> {
281+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
282+
ConnectDTO connectDto = ConnectDTO.builder()
283+
.name("SOME OTHER CONNECT")
284+
.build();
285+
Mono<Boolean> consumerGroupAccessibleMono =
286+
accessControlService.isConnectAccessible(connectDto, DEV_CLUSTER);
287+
StepVerifier.create(consumerGroupAccessibleMono)
288+
.expectNext(false)
289+
.expectComplete()
290+
.verify();
291+
});
292+
}
293+
294+
}

0 commit comments

Comments
 (0)