Skip to content

Commit

Permalink
added more test, closes #729
Browse files Browse the repository at this point in the history
  • Loading branch information
zambrinf committed Jan 12, 2025
1 parent f868570 commit f4098a1
Show file tree
Hide file tree
Showing 3 changed files with 243 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.kafbat.ui.service.rbac;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;

import io.kafbat.ui.AbstractIntegrationTest;
import io.kafbat.ui.service.rbac.extractor.GoogleAuthorityExtractor;
import io.kafbat.ui.service.rbac.extractor.ProviderAuthorityExtractor;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;

/**
* Test case for Properties initializer.
*/
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@ContextConfiguration(initializers = AccessControlServiceInitPropertiesTest.PropertiesInitializer.class)
class AccessControlServiceInitPropertiesTest extends AbstractIntegrationTest {

public static class PropertiesInitializer extends AbstractIntegrationTest.Initializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {

@Override
public void initialize(@NotNull ConfigurableApplicationContext applicationContext) {
System.setProperty("rbac.roles[0].name", "memelords");
System.setProperty("rbac.roles[0].clusters[0]", "local");

System.setProperty("rbac.roles[0].subjects[0].provider", "oauth_google");
System.setProperty("rbac.roles[0].subjects[0].type", "domain");
System.setProperty("rbac.roles[0].subjects[0].value", "katbat.dev");

System.setProperty("rbac.roles[0].subjects[1].provider", "oauth_google");
System.setProperty("rbac.roles[0].subjects[1].type", "user");
System.setProperty("rbac.roles[0].subjects[1].value", "[email protected]");

System.setProperty("rbac.roles[0].permissions[0].resource", "applicationconfig");
System.setProperty("rbac.roles[0].permissions[0].actions", "all");
}
}

@Autowired
AccessControlService accessControlService;

@Test
void rbacEnabled() {
assertTrue(accessControlService.isRbacEnabled());

Set<ProviderAuthorityExtractor> oauthExtractors = accessControlService.getOauthExtractors();
assertThat(oauthExtractors)
.hasSize(1)
.anyMatch(ext -> ext instanceof GoogleAuthorityExtractor);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package io.kafbat.ui.service.rbac;

import static io.kafbat.ui.service.rbac.MockedRbacUtils.CONNECT_NAME;
import static io.kafbat.ui.service.rbac.MockedRbacUtils.CONSUMER_GROUP_NAME;
import static io.kafbat.ui.service.rbac.MockedRbacUtils.DEV_ROLE;
import static io.kafbat.ui.service.rbac.MockedRbacUtils.PROD_CLUSTER;
import static io.kafbat.ui.service.rbac.MockedRbacUtils.SCHEMA_NAME;
import static io.kafbat.ui.service.rbac.MockedRbacUtils.TOPIC_NAME;
import static io.kafbat.ui.service.rbac.MockedRbacUtils.getAccessContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

import io.kafbat.ui.AbstractIntegrationTest;
import io.kafbat.ui.config.auth.RbacUser;
import io.kafbat.ui.model.ClusterDTO;
import io.kafbat.ui.model.ConnectDTO;
import io.kafbat.ui.model.InternalTopic;
import io.kafbat.ui.model.rbac.AccessContext;
import io.kafbat.ui.model.rbac.Role;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.test.annotation.DirtiesContext;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;

/**
* Test cases for AccessControlService when RBAC is disabled.
* Using PROD cluster and user DEV role for all tests.
*/
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
class AccessControlServiceRbacDisabledTest extends AbstractIntegrationTest {

@Autowired
AccessControlService accessControlService;

@Mock
SecurityContext securityContext;

@Mock
Authentication authentication;

@Mock
RbacUser user;

@BeforeEach
void setUp() {
// Mock security context
when(securityContext.getAuthentication()).thenReturn(authentication);
when(authentication.getPrincipal()).thenReturn(user);
}

public void withSecurityContext(Runnable runnable) {
try (MockedStatic<ReactiveSecurityContextHolder> ctxHolder = Mockito.mockStatic(
ReactiveSecurityContextHolder.class)) {
// Mock static method to get security context
ctxHolder.when(ReactiveSecurityContextHolder::getContext).thenReturn(Mono.just(securityContext));
runnable.run();
}
}

@Test
void validateAccess() {
withSecurityContext(() -> {
when(user.groups()).thenReturn(List.of(DEV_ROLE));
AccessContext context = getAccessContext(PROD_CLUSTER, true);
Mono<Void> validateAccessMono = accessControlService.validateAccess(context);
StepVerifier.create(validateAccessMono)
.expectComplete()
.verify();
});
}

@Test
void isClusterAccessible() {
withSecurityContext(() -> {
when(user.groups()).thenReturn(List.of(DEV_ROLE));
ClusterDTO clusterDto = new ClusterDTO();
clusterDto.setName(PROD_CLUSTER);
Mono<Boolean> clusterAccessibleMono = accessControlService.isClusterAccessible(clusterDto);
StepVerifier.create(clusterAccessibleMono)
.expectNext(true)
.expectComplete()
.verify();
});
}

@Test
void filterViewableTopics() {
withSecurityContext(() -> {
when(user.groups()).thenReturn(List.of(DEV_ROLE));
List<InternalTopic> topics = List.of(
InternalTopic.builder()
.name(TOPIC_NAME)
.build()
);
Mono<List<InternalTopic>> filterTopicsMono = accessControlService.filterViewableTopics(topics, PROD_CLUSTER);
StepVerifier.create(filterTopicsMono)
.expectNextMatches(responseTopics -> responseTopics.stream().anyMatch(t -> t.getName().equals(TOPIC_NAME)))
.expectComplete()
.verify();
});
}

@Test
void isConsumerGroupAccessible() {
withSecurityContext(() -> {
when(user.groups()).thenReturn(List.of(DEV_ROLE));
Mono<Boolean> consumerGroupAccessibleMono =
accessControlService.isConsumerGroupAccessible(CONSUMER_GROUP_NAME, PROD_CLUSTER);
StepVerifier.create(consumerGroupAccessibleMono)
.expectNext(true)
.expectComplete()
.verify();
});
}

@Test
void isSchemaAccessible() {
withSecurityContext(() -> {
when(user.groups()).thenReturn(List.of(DEV_ROLE));
Mono<Boolean> consumerGroupAccessibleMono =
accessControlService.isSchemaAccessible(SCHEMA_NAME, PROD_CLUSTER);
StepVerifier.create(consumerGroupAccessibleMono)
.expectNext(true)
.expectComplete()
.verify();
});
}

@Test
void isConnectAccessible() {
withSecurityContext(() -> {
when(user.groups()).thenReturn(List.of(DEV_ROLE));
Mono<Boolean> consumerGroupAccessibleMono =
accessControlService.isConnectAccessible(CONNECT_NAME, PROD_CLUSTER);
StepVerifier.create(consumerGroupAccessibleMono)
.expectNext(true)
.expectComplete()
.verify();
});
}

@Test
void isConnectAccessibleDto() {
withSecurityContext(() -> {
when(user.groups()).thenReturn(List.of(DEV_ROLE));
ConnectDTO connectDto = ConnectDTO.builder()
.name(CONNECT_NAME)
.build();
Mono<Boolean> consumerGroupAccessibleMono =
accessControlService.isConnectAccessible(connectDto, PROD_CLUSTER);
StepVerifier.create(consumerGroupAccessibleMono)
.expectNext(true)
.expectComplete()
.verify();
});
}

@Test
void getRoles() {
List<Role> roles = accessControlService.getRoles();
assertThat(roles).isEmpty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static io.kafbat.ui.service.rbac.MockedRbacUtils.SCHEMA_NAME;
import static io.kafbat.ui.service.rbac.MockedRbacUtils.TOPIC_NAME;
import static io.kafbat.ui.service.rbac.MockedRbacUtils.getAccessContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

Expand All @@ -31,13 +32,15 @@
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.util.ReflectionTestUtils;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;

/**
* Test cases for AccessControlService when RBAC is enabled.
*/
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
class AccessControlServiceRbacEnabledTest extends AbstractIntegrationTest {

@Autowired
Expand Down Expand Up @@ -147,8 +150,6 @@ void isClusterAccessible_deniedCluster() {
void filterViewableTopics() {
withSecurityContext(() -> {
when(user.groups()).thenReturn(List.of(DEV_ROLE));
ClusterDTO clusterDto = new ClusterDTO();
clusterDto.setName(DEV_CLUSTER);
List<InternalTopic> topics = List.of(
InternalTopic.builder()
.name(TOPIC_NAME)
Expand All @@ -166,8 +167,6 @@ void filterViewableTopics() {
void filterViewableTopics_notAccessibleTopic() {
withSecurityContext(() -> {
when(user.groups()).thenReturn(List.of(DEV_ROLE));
ClusterDTO clusterDto = new ClusterDTO();
clusterDto.setName(DEV_CLUSTER);
List<InternalTopic> topics = List.of(
InternalTopic.builder()
.name("some other topic")
Expand Down Expand Up @@ -291,4 +290,12 @@ void isConnectAccessibleDto_notAccessible() {
});
}

@Test
void getRoles() {
List<Role> roles = accessControlService.getRoles();
assertThat(roles).hasSize(2)
.anyMatch(role -> role.getName().equals(DEV_ROLE))
.anyMatch(role -> role.getName().equals(ADMIN_ROLE));
}

}

0 comments on commit f4098a1

Please sign in to comment.