Skip to content

Commit 6a22b4a

Browse files
authored
BE: RBAC: Add integration tests for AD auth (#726)
1 parent eaeb4a4 commit 6a22b4a

File tree

3 files changed

+222
-0
lines changed

3 files changed

+222
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package io.kafbat.ui;
2+
3+
import static io.kafbat.ui.AbstractIntegrationTest.LOCAL;
4+
import static io.kafbat.ui.container.ActiveDirectoryContainer.DOMAIN;
5+
import static io.kafbat.ui.container.ActiveDirectoryContainer.EMPTY_PERMISSIONS_USER;
6+
import static io.kafbat.ui.container.ActiveDirectoryContainer.FIRST_USER_WITH_GROUP;
7+
import static io.kafbat.ui.container.ActiveDirectoryContainer.PASSWORD;
8+
import static io.kafbat.ui.container.ActiveDirectoryContainer.SECOND_USER_WITH_GROUP;
9+
import static io.kafbat.ui.container.ActiveDirectoryContainer.USER_WITHOUT_GROUP;
10+
import static org.junit.jupiter.api.Assertions.assertEquals;
11+
import static org.junit.jupiter.api.Assertions.assertFalse;
12+
import static org.junit.jupiter.api.Assertions.assertNotNull;
13+
import static org.junit.jupiter.api.Assertions.assertTrue;
14+
15+
import io.kafbat.ui.container.ActiveDirectoryContainer;
16+
import io.kafbat.ui.model.AuthenticationInfoDTO;
17+
import io.kafbat.ui.model.ResourceTypeDTO;
18+
import io.kafbat.ui.model.UserPermissionDTO;
19+
import java.util.List;
20+
import java.util.Objects;
21+
import org.jetbrains.annotations.NotNull;
22+
import org.junit.jupiter.api.AfterAll;
23+
import org.junit.jupiter.api.BeforeAll;
24+
import org.junit.jupiter.api.Test;
25+
import org.springframework.beans.factory.annotation.Autowired;
26+
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
27+
import org.springframework.boot.test.context.SpringBootTest;
28+
import org.springframework.context.ApplicationContextInitializer;
29+
import org.springframework.context.ConfigurableApplicationContext;
30+
import org.springframework.http.MediaType;
31+
import org.springframework.test.context.ActiveProfiles;
32+
import org.springframework.test.context.ContextConfiguration;
33+
import org.springframework.test.web.reactive.server.WebTestClient;
34+
import org.springframework.web.reactive.function.BodyInserters;
35+
36+
@SpringBootTest
37+
@ActiveProfiles("rbac-ad")
38+
@AutoConfigureWebTestClient(timeout = "60000")
39+
@ContextConfiguration(initializers = {ActiveDirectoryIntegrationTest.Initializer.class})
40+
public class ActiveDirectoryIntegrationTest {
41+
private static final String SESSION = "SESSION";
42+
43+
private static final ActiveDirectoryContainer ACTIVE_DIRECTORY = new ActiveDirectoryContainer();
44+
45+
@Autowired
46+
private WebTestClient webTestClient;
47+
48+
@BeforeAll
49+
public static void setup() {
50+
ACTIVE_DIRECTORY.start();
51+
}
52+
53+
@AfterAll
54+
public static void shutdown() {
55+
ACTIVE_DIRECTORY.stop();
56+
}
57+
58+
@Test
59+
public void testUserPermissions() {
60+
AuthenticationInfoDTO info = authenticationInfo(FIRST_USER_WITH_GROUP);
61+
62+
assertNotNull(info);
63+
assertTrue(info.getRbacEnabled());
64+
65+
List<UserPermissionDTO> permissions = info.getUserInfo().getPermissions();
66+
67+
assertFalse(permissions.isEmpty());
68+
assertTrue(permissions.stream().anyMatch(permission ->
69+
permission.getClusters().contains(LOCAL) && permission.getResource() == ResourceTypeDTO.TOPIC));
70+
assertEquals(permissions, authenticationInfo(SECOND_USER_WITH_GROUP).getUserInfo().getPermissions());
71+
assertEquals(permissions, authenticationInfo(USER_WITHOUT_GROUP).getUserInfo().getPermissions());
72+
}
73+
74+
@Test
75+
public void testEmptyPermissions() {
76+
assertTrue(Objects.requireNonNull(authenticationInfo(EMPTY_PERMISSIONS_USER))
77+
.getUserInfo()
78+
.getPermissions()
79+
.isEmpty()
80+
);
81+
}
82+
83+
private String session(String name) {
84+
return Objects.requireNonNull(
85+
webTestClient
86+
.post()
87+
.uri("/login")
88+
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
89+
.body(BodyInserters.fromFormData("username", name).with("password", PASSWORD))
90+
.exchange()
91+
.expectStatus()
92+
.isFound()
93+
.returnResult(String.class)
94+
.getResponseCookies()
95+
.getFirst(SESSION))
96+
.getValue();
97+
}
98+
99+
private AuthenticationInfoDTO authenticationInfo(String name) {
100+
return webTestClient
101+
.get()
102+
.uri("/api/authorization")
103+
.cookie(SESSION, session(name))
104+
.exchange()
105+
.expectStatus()
106+
.isOk()
107+
.returnResult(AuthenticationInfoDTO.class)
108+
.getResponseBody()
109+
.blockFirst();
110+
}
111+
112+
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
113+
@Override
114+
public void initialize(@NotNull ConfigurableApplicationContext context) {
115+
System.setProperty("spring.ldap.urls", ACTIVE_DIRECTORY.getLdapUrl());
116+
System.setProperty("oauth2.ldap.activeDirectory", "true");
117+
System.setProperty("oauth2.ldap.activeDirectory.domain", DOMAIN);
118+
}
119+
}
120+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package io.kafbat.ui.container;
2+
3+
import com.github.dockerjava.api.command.InspectContainerResponse;
4+
import java.io.IOException;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.testcontainers.containers.GenericContainer;
7+
import org.testcontainers.utility.DockerImageName;
8+
9+
@Slf4j
10+
public class ActiveDirectoryContainer extends GenericContainer<ActiveDirectoryContainer> {
11+
public static final String DOMAIN = "corp.kafbat.io";
12+
public static final String PASSWORD = "StrongPassword123";
13+
public static final String FIRST_USER_WITH_GROUP = "JohnDoe";
14+
public static final String SECOND_USER_WITH_GROUP = "JohnWick";
15+
public static final String USER_WITHOUT_GROUP = "JackSmith";
16+
public static final String EMPTY_PERMISSIONS_USER = "JohnJames";
17+
18+
private static final String DOMAIN_DC = "dc=corp,dc=kafbat,dc=io";
19+
private static final String GROUP = "group";
20+
private static final String FIRST_GROUP = "firstGroup";
21+
private static final String SECOND_GROUP = "secondGroup";
22+
private static final String DOMAIN_EMAIL = "kafbat.io";
23+
private static final String SAMBA_TOOL = "samba-tool";
24+
private static final int LDAP_PORT = 389;
25+
private static final DockerImageName IMAGE_NAME = DockerImageName.parse("nowsci/samba-domain:latest");
26+
27+
public ActiveDirectoryContainer() {
28+
super(IMAGE_NAME);
29+
30+
withExposedPorts(LDAP_PORT);
31+
32+
withEnv("DOMAIN", DOMAIN);
33+
withEnv("DOMAIN_DC", DOMAIN_DC);
34+
withEnv("DOMAIN_EMAIL", DOMAIN_EMAIL);
35+
withEnv("DOMAINPASS", PASSWORD);
36+
withEnv("NOCOMPLEXITY", "true");
37+
withEnv("INSECURELDAP", "true");
38+
39+
withPrivilegedMode(true);
40+
}
41+
42+
protected void containerIsStarted(InspectContainerResponse containerInfo) {
43+
createUser(EMPTY_PERMISSIONS_USER);
44+
createUser(USER_WITHOUT_GROUP);
45+
createUser(FIRST_USER_WITH_GROUP);
46+
createUser(SECOND_USER_WITH_GROUP);
47+
48+
exec(SAMBA_TOOL, GROUP, "add", FIRST_GROUP);
49+
exec(SAMBA_TOOL, GROUP, "add", SECOND_GROUP);
50+
exec(SAMBA_TOOL, GROUP, "addmembers", FIRST_GROUP, FIRST_USER_WITH_GROUP);
51+
exec(SAMBA_TOOL, GROUP, "addmembers", SECOND_GROUP, SECOND_USER_WITH_GROUP);
52+
}
53+
54+
public String getLdapUrl() {
55+
return String.format("ldap://%s:%s", getHost(), getMappedPort(LDAP_PORT));
56+
}
57+
58+
private void createUser(String name) {
59+
exec(SAMBA_TOOL, "user", "create", name, PASSWORD, "--mail-address", name + '@' + DOMAIN_EMAIL);
60+
exec(SAMBA_TOOL, "user", "setexpiry", name, "--noexpiry");
61+
}
62+
63+
private void exec(String... cmd) {
64+
ExecResult result;
65+
try {
66+
result = execInContainer(cmd);
67+
} catch (IOException | InterruptedException e) {
68+
throw new RuntimeException(e);
69+
}
70+
71+
if (result.getStdout() != null && !result.getStdout().isEmpty()) {
72+
log.info("Output: {}", result.getStdout());
73+
}
74+
75+
if (result.getExitCode() != 0) {
76+
throw new IllegalStateException(result.toString());
77+
}
78+
}
79+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
auth:
2+
type: LDAP
3+
rbac:
4+
roles:
5+
- name: "roleName"
6+
clusters:
7+
- local
8+
subjects:
9+
- provider: ldap_ad
10+
type: group
11+
value: firstGroup
12+
- provider: ldap_ad
13+
type: group
14+
value: secondGroup
15+
- provider: ldap_ad
16+
type: user
17+
value: JackSmith
18+
permissions:
19+
- resource: applicationconfig
20+
actions: all
21+
- resource: topic
22+
value: ".*"
23+
actions: all

0 commit comments

Comments
 (0)