Skip to content

Fix regex tests #1105

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

Merged
merged 3 commits into from
May 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/src/main/java/io/kafbat/ui/model/rbac/Role.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.google.common.base.Preconditions.checkArgument;

import java.util.ArrayList;
import java.util.List;
import lombok.Data;

Expand All @@ -11,7 +12,7 @@ public class Role {
String name;
List<String> clusters;
List<Subject> subjects;
List<Permission> permissions;
List<Permission> permissions = new ArrayList<>();

public void validate() {
checkArgument(clusters != null && !clusters.isEmpty(), "Role clusters cannot be empty");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,17 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
import static org.springframework.security.oauth2.client.registration.ClientRegistration.withRegistrationId;

import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import io.kafbat.ui.config.auth.OAuthProperties;
import io.kafbat.ui.model.rbac.Role;
import io.kafbat.ui.config.auth.RoleBasedAccessControlProperties;
import io.kafbat.ui.service.rbac.AccessControlService;
import io.kafbat.ui.service.rbac.extractor.CognitoAuthorityExtractor;
import io.kafbat.ui.service.rbac.extractor.GithubAuthorityExtractor;
import io.kafbat.ui.service.rbac.extractor.GoogleAuthorityExtractor;
import io.kafbat.ui.service.rbac.extractor.OauthAuthorityExtractor;
import io.kafbat.ui.service.rbac.extractor.ProviderAuthorityExtractor;
import io.kafbat.ui.util.AccessControlServiceMock;
import java.io.IOException;
import java.io.InputStream;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
Expand All @@ -28,39 +24,40 @@
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;

import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties(RoleBasedAccessControlProperties.class)
@TestPropertySource(
locations = "classpath:application-roles-definition.yml",
factory = YamlPropertySourceFactory.class
)
public class RegexBasedProviderAuthorityExtractorTest {


private final AccessControlService accessControlService = new AccessControlServiceMock().getMock();
ProviderAuthorityExtractor extractor;
@Autowired
private RoleBasedAccessControlProperties properties;
private AccessControlService accessControlService;

@BeforeEach
void setUp() throws IOException {

YAMLMapper mapper = new YAMLMapper();

InputStream rolesFile = this.getClass()
.getClassLoader()
.getResourceAsStream("roles_definition.yaml");

Role[] roles = mapper.readValue(rolesFile, Role[].class);

when(accessControlService.getRoles()).thenReturn(List.of(roles));

public void configure() {
this.accessControlService = new AccessControlServiceMock(properties.getRoles()).getMock();
}

@SneakyThrows
@Test
void extractOauth2Authorities() {

extractor = new OauthAuthorityExtractor();
ProviderAuthorityExtractor extractor = new OauthAuthorityExtractor();

OAuth2User oauth2User = new DefaultOAuth2User(
AuthorityUtils.createAuthorityList("SCOPE_message:read"),
Expand All @@ -84,7 +81,7 @@ void extractOauth2Authorities() {
@Test()
void extractOauth2Authorities_blankEmail() {

extractor = new OauthAuthorityExtractor();
ProviderAuthorityExtractor extractor = new OauthAuthorityExtractor();

OAuth2User oauth2User = new DefaultOAuth2User(
AuthorityUtils.createAuthorityList("SCOPE_message:read"),
Expand All @@ -108,7 +105,7 @@ void extractOauth2Authorities_blankEmail() {
@Test
void extractCognitoAuthorities() {

extractor = new CognitoAuthorityExtractor();
ProviderAuthorityExtractor extractor = new CognitoAuthorityExtractor();

OAuth2User oauth2User = new DefaultOAuth2User(
AuthorityUtils.createAuthorityList("SCOPE_message:read"),
Expand All @@ -133,7 +130,7 @@ void extractCognitoAuthorities() {
@Test
void extractGithubAuthorities() {

extractor = new GithubAuthorityExtractor();
ProviderAuthorityExtractor extractor = new GithubAuthorityExtractor();

OAuth2User oauth2User = new DefaultOAuth2User(
AuthorityUtils.createAuthorityList("SCOPE_message:read"),
Expand Down Expand Up @@ -170,7 +167,7 @@ void extractGithubAuthorities() {
@Test
void extractGoogleAuthorities() {

extractor = new GoogleAuthorityExtractor();
ProviderAuthorityExtractor extractor = new GoogleAuthorityExtractor();

OAuth2User oauth2User = new DefaultOAuth2User(
AuthorityUtils.createAuthorityList("SCOPE_message:read"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.kafbat.ui.config;

import java.io.IOException;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;

public class YamlPropertySourceFactory implements PropertySourceFactory {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

@Override
public @NotNull PropertySource<?> createPropertySource(String name, EncodedResource resource)
throws IOException {
List<PropertySource<?>> loaded = loader.load(name, resource.getResource());
if (loaded.size() == 1) {
return loaded.getFirst();
} else {
throw new IOException(resource.getResource().getFilename());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

import io.kafbat.ui.model.rbac.Role;
import io.kafbat.ui.service.rbac.AccessControlService;
import java.util.List;
import org.mockito.Mockito;
import reactor.core.publisher.Mono;

public class AccessControlServiceMock {
private final List<Role> roles;

public AccessControlServiceMock(List<Role> roles) {
this.roles = roles;
}

public AccessControlServiceMock() {
this(List.of());
}


public AccessControlService getMock() {
AccessControlService mock = Mockito.mock(AccessControlService.class);
Expand All @@ -17,6 +29,7 @@ public AccessControlService getMock() {
when(mock.isSchemaAccessible(anyString(), anyString())).thenReturn(Mono.just(true));

when(mock.filterViewableTopics(any(), any())).then(invocation -> Mono.just(invocation.getArgument(0)));
when(mock.getRoles()).thenReturn(roles);

return mock;
}
Expand Down
72 changes: 72 additions & 0 deletions api/src/test/resources/application-roles-definition.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
rbac:
roles:
- name: 'admin'
subjects:
- provider: 'OAUTH'
value: 'ROLE-[A-Z]+'
type: 'role'
regex: 'true'
- provider: 'OAUTH_COGNITO'
value: 'ROLE-ADMIN'
type: 'group'
- provider: 'OAUTH_GOOGLE'
type: 'domain'
value: 'memelord.lol'
clusters:
- local
- remote
permissions:
- resource: APPLICATIONCONFIG
actions: [ all ]
- name: 'viewer'
subjects:
- provider: 'LDAP'
value: 'CS-XXX'
type: 'kafka-viewer'
- provider: 'OAUTH'
value: '.*@kafka.com'
type: 'user'
regex: 'true'
- provider: 'OAUTH_COGNITO'
value: '.*@kafka.com'
type: 'user'
regex: 'true'
- provider: 'OAUTH_GITHUB'
value: '.*@kafka.com'
type: 'user'
regex: 'true'
- provider: 'OAUTH_GOOGLE'
value: 'john@kafka.com'
type: 'user'
clusters:
- remote
permissions:
- resource: APPLICATIONCONFIG
actions: [ all ]
- name: 'editor'
subjects:
- provider: 'OAUTH'
value: 'ROLE_EDITOR'
type: 'role'
clusters:
- local
permissions:
- resource: APPLICATIONCONFIG
actions: [ all ]
- name: "no one's role"
clusters:
- local
- remote
subjects:
- provider: 'OAUTH'
value: '.*XXX'
type: 'role'
- provider: 'OAUTH_GITHUB'
value: '.*XXX'
type: 'user'
- provider: 'OAUTH_COGNITO'
value: '.*XXX'
type: 'user'
- provider: 'OAUTH_GOOGLE'
value: '.*XXX'
type: 'domain'
67 changes: 0 additions & 67 deletions api/src/test/resources/roles_definition.yaml

This file was deleted.

Loading