Skip to content

Commit b008fa9

Browse files
authored
Merge pull request #1 from kafbat/main
sync with upstream
2 parents bacf1b4 + 0f0e2a9 commit b008fa9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1231
-202
lines changed

.java-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
21
Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,53 @@
11
package io.kafbat.ui.config.auth;
22

3+
import io.kafbat.ui.util.EmptyRedirectStrategy;
4+
import java.net.URI;
5+
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
6+
import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler;
7+
38
abstract class AbstractAuthSecurityConfig {
49

510
protected AbstractAuthSecurityConfig() {
611

712
}
813

14+
protected static final String LOGIN_URL = "/login";
15+
protected static final String LOGOUT_URL = "/auth?logout";
16+
917
protected static final String[] AUTH_WHITELIST = {
10-
"/css/**",
11-
"/js/**",
12-
"/media/**",
18+
/* STATIC */
19+
"/index.html",
20+
"/assets/**",
21+
"/manifest.json",
22+
"/favicon.svg",
23+
"/favicon/**",
24+
25+
"/static/**",
1326
"/resources/**",
27+
28+
/* ACTUATOR */
1429
"/actuator/health/**",
1530
"/actuator/info",
1631
"/actuator/prometheus",
17-
"/auth",
32+
33+
/* AUTH */
1834
"/login",
1935
"/logout",
2036
"/oauth2/**",
21-
"/static/**"
37+
"/api/config/authentication",
38+
"/api/authorization"
2239
};
2340

41+
protected RedirectServerAuthenticationSuccessHandler emptyRedirectSuccessHandler() {
42+
final var authHandler = new RedirectServerAuthenticationSuccessHandler();
43+
authHandler.setRedirectStrategy(new EmptyRedirectStrategy());
44+
return authHandler;
45+
}
46+
47+
protected RedirectServerLogoutSuccessHandler redirectLogoutSuccessHandler() {
48+
final var logoutSuccessHandler = new RedirectServerLogoutSuccessHandler();
49+
logoutSuccessHandler.setLogoutSuccessUrl(URI.create(LOGOUT_URL));
50+
return logoutSuccessHandler;
51+
}
52+
2453
}
Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package io.kafbat.ui.config.auth;
22

33
import io.kafbat.ui.util.EmptyRedirectStrategy;
4+
import io.kafbat.ui.util.StaticFileWebFilter;
45
import java.net.URI;
56
import lombok.extern.slf4j.Slf4j;
67
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
78
import org.springframework.context.annotation.Bean;
89
import org.springframework.context.annotation.Configuration;
910
import org.springframework.http.HttpMethod;
1011
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
12+
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
1113
import org.springframework.security.config.web.server.ServerHttpSecurity;
1214
import org.springframework.security.web.server.SecurityWebFilterChain;
1315
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
@@ -20,32 +22,28 @@
2022
@Slf4j
2123
public class BasicAuthSecurityConfig extends AbstractAuthSecurityConfig {
2224

23-
public static final String LOGIN_URL = "/auth";
24-
public static final String LOGOUT_URL = "/auth?logout";
25-
2625
@Bean
2726
public SecurityWebFilterChain configure(ServerHttpSecurity http) {
2827
log.info("Configuring LOGIN_FORM authentication.");
2928

30-
final var authHandler = new RedirectServerAuthenticationSuccessHandler();
31-
authHandler.setRedirectStrategy(new EmptyRedirectStrategy());
32-
33-
final var logoutSuccessHandler = new RedirectServerLogoutSuccessHandler();
34-
logoutSuccessHandler.setLogoutSuccessUrl(URI.create(LOGOUT_URL));
35-
36-
37-
return http.authorizeExchange(spec -> spec
29+
var builder = http.authorizeExchange(spec -> spec
3830
.pathMatchers(AUTH_WHITELIST)
3931
.permitAll()
4032
.anyExchange()
4133
.authenticated()
4234
)
43-
.formLogin(spec -> spec.loginPage(LOGIN_URL).authenticationSuccessHandler(authHandler))
35+
.formLogin(form -> form
36+
.loginPage(LOGIN_URL)
37+
.authenticationSuccessHandler(emptyRedirectSuccessHandler())
38+
)
4439
.logout(spec -> spec
45-
.logoutSuccessHandler(logoutSuccessHandler)
40+
.logoutSuccessHandler(redirectLogoutSuccessHandler())
4641
.requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, "/logout")))
47-
.csrf(ServerHttpSecurity.CsrfSpec::disable)
48-
.build();
42+
.csrf(ServerHttpSecurity.CsrfSpec::disable);
43+
44+
builder.addFilterAt(new StaticFileWebFilter(), SecurityWebFiltersOrder.LOGIN_PAGE_GENERATING);
45+
46+
return builder.build();
4947
}
5048

5149
}

api/src/main/java/io/kafbat/ui/config/auth/LdapSecurityConfig.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package io.kafbat.ui.config.auth;
22

3-
import static io.kafbat.ui.config.auth.AbstractAuthSecurityConfig.AUTH_WHITELIST;
4-
53
import io.kafbat.ui.service.rbac.AccessControlService;
64
import io.kafbat.ui.service.rbac.extractor.RbacLdapAuthoritiesExtractor;
5+
import io.kafbat.ui.util.StaticFileWebFilter;
76
import java.util.Collection;
87
import java.util.List;
98
import java.util.Optional;
@@ -14,15 +13,16 @@
1413
import org.springframework.context.ApplicationContext;
1514
import org.springframework.context.annotation.Bean;
1615
import org.springframework.context.annotation.Configuration;
16+
import org.springframework.http.HttpMethod;
1717
import org.springframework.ldap.core.DirContextOperations;
1818
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
1919
import org.springframework.ldap.core.support.LdapContextSource;
2020
import org.springframework.security.authentication.AuthenticationManager;
2121
import org.springframework.security.authentication.ProviderManager;
2222
import org.springframework.security.authentication.ReactiveAuthenticationManager;
2323
import org.springframework.security.authentication.ReactiveAuthenticationManagerAdapter;
24-
import org.springframework.security.config.Customizer;
2524
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
25+
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
2626
import org.springframework.security.config.web.server.ServerHttpSecurity;
2727
import org.springframework.security.core.GrantedAuthority;
2828
import org.springframework.security.core.userdetails.UserDetails;
@@ -36,14 +36,15 @@
3636
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
3737
import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
3838
import org.springframework.security.web.server.SecurityWebFilterChain;
39+
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
3940

4041
@Configuration
4142
@EnableWebFluxSecurity
4243
@ConditionalOnProperty(value = "auth.type", havingValue = "LDAP")
4344
@EnableConfigurationProperties(LdapProperties.class)
4445
@RequiredArgsConstructor
4546
@Slf4j
46-
public class LdapSecurityConfig {
47+
public class LdapSecurityConfig extends AbstractAuthSecurityConfig {
4748

4849
private final LdapProperties props;
4950

@@ -121,16 +122,24 @@ public SecurityWebFilterChain configureLdap(ServerHttpSecurity http) {
121122
log.info("Active Directory support for LDAP has been enabled.");
122123
}
123124

124-
return http.authorizeExchange(spec -> spec
125+
var builder = http.authorizeExchange(spec -> spec
125126
.pathMatchers(AUTH_WHITELIST)
126127
.permitAll()
127128
.anyExchange()
128129
.authenticated()
129130
)
130-
.formLogin(Customizer.withDefaults())
131-
.logout(Customizer.withDefaults())
132-
.csrf(ServerHttpSecurity.CsrfSpec::disable)
133-
.build();
131+
.formLogin(form -> form
132+
.loginPage(LOGIN_URL)
133+
.authenticationSuccessHandler(emptyRedirectSuccessHandler())
134+
)
135+
.logout(spec -> spec
136+
.logoutSuccessHandler(redirectLogoutSuccessHandler())
137+
.requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, "/logout")))
138+
.csrf(ServerHttpSecurity.CsrfSpec::disable);
139+
140+
builder.addFilterAt(new StaticFileWebFilter(), SecurityWebFiltersOrder.LOGIN_PAGE_GENERATING);
141+
142+
return builder.build();
134143
}
135144

136145
private static class UserDetailsMapper extends LdapUserDetailsMapper {

api/src/main/java/io/kafbat/ui/config/auth/OAuthSecurityConfig.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.kafbat.ui.config.auth.logout.OAuthLogoutSuccessHandler;
44
import io.kafbat.ui.service.rbac.AccessControlService;
55
import io.kafbat.ui.service.rbac.extractor.ProviderAuthorityExtractor;
6+
import io.kafbat.ui.util.StaticFileWebFilter;
67
import java.util.ArrayList;
78
import java.util.List;
89
import java.util.Map;
@@ -19,6 +20,7 @@
1920
import org.springframework.security.config.Customizer;
2021
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
2122
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
23+
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
2224
import org.springframework.security.config.web.server.ServerHttpSecurity;
2325
import org.springframework.security.oauth2.client.oidc.userinfo.OidcReactiveOAuth2UserService;
2426
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
@@ -50,16 +52,20 @@ public class OAuthSecurityConfig extends AbstractAuthSecurityConfig {
5052
public SecurityWebFilterChain configure(ServerHttpSecurity http, OAuthLogoutSuccessHandler logoutHandler) {
5153
log.info("Configuring OAUTH2 authentication.");
5254

53-
return http.authorizeExchange(spec -> spec
55+
var builder = http.authorizeExchange(spec -> spec
5456
.pathMatchers(AUTH_WHITELIST)
5557
.permitAll()
5658
.anyExchange()
5759
.authenticated()
5860
)
5961
.oauth2Login(Customizer.withDefaults())
6062
.logout(spec -> spec.logoutSuccessHandler(logoutHandler))
61-
.csrf(ServerHttpSecurity.CsrfSpec::disable)
62-
.build();
63+
.csrf(ServerHttpSecurity.CsrfSpec::disable);
64+
65+
66+
builder.addFilterAt(new StaticFileWebFilter(), SecurityWebFiltersOrder.LOGIN_PAGE_GENERATING);
67+
68+
return builder.build();
6369
}
6470

6571
@Bean

api/src/main/java/io/kafbat/ui/controller/ApplicationConfigController.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.kafbat.ui.api.ApplicationConfigApi;
77
import io.kafbat.ui.config.ClustersProperties;
88
import io.kafbat.ui.model.ActionDTO;
9+
import io.kafbat.ui.model.AppAuthenticationSettingsDTO;
910
import io.kafbat.ui.model.ApplicationConfigDTO;
1011
import io.kafbat.ui.model.ApplicationConfigPropertiesDTO;
1112
import io.kafbat.ui.model.ApplicationConfigValidationDTO;
@@ -66,6 +67,13 @@ public Mono<ResponseEntity<ApplicationInfoDTO>> getApplicationInfo(ServerWebExch
6667
return Mono.just(applicationInfoService.getApplicationInfo()).map(ResponseEntity::ok);
6768
}
6869

70+
@Override
71+
public Mono<ResponseEntity<AppAuthenticationSettingsDTO>> getAuthenticationSettings(
72+
ServerWebExchange exchange) {
73+
return Mono.just(applicationInfoService.getAuthenticationProperties())
74+
.map(ResponseEntity::ok);
75+
}
76+
6977
@Override
7078
public Mono<ResponseEntity<ApplicationConfigDTO>> getCurrentConfig(ServerWebExchange exchange) {
7179
var context = AccessContext.builder()
@@ -109,7 +117,7 @@ public Mono<ResponseEntity<UploadedFileInfoDTO>> uploadConfigRelatedFile(Flux<Pa
109117
.then(fileFlux.single())
110118
.flatMap(file ->
111119
dynamicConfigOperations.uploadConfigRelatedFile((FilePart) file)
112-
.map(path -> new UploadedFileInfoDTO().location(path.toString()))
120+
.map(path -> new UploadedFileInfoDTO(path.toString()))
113121
.map(ResponseEntity::ok))
114122
.doOnEach(sig -> audit(context, sig));
115123
}

api/src/main/java/io/kafbat/ui/controller/AuthController.java

Lines changed: 0 additions & 99 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.kafbat.ui.controller;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.core.io.ClassPathResource;
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.web.bind.annotation.RestController;
8+
import reactor.core.publisher.Mono;
9+
10+
@RestController
11+
@RequiredArgsConstructor
12+
@Slf4j
13+
public class AuthenticationController {
14+
15+
private static final String INDEX_HTML = "/static/index.html";
16+
17+
@GetMapping(value = "/login", produces = {"text/html"})
18+
public Mono<ClassPathResource> getLoginPage() {
19+
return Mono.just(new ClassPathResource(INDEX_HTML));
20+
}
21+
22+
}

api/src/main/java/io/kafbat/ui/controller/AccessController.java renamed to api/src/main/java/io/kafbat/ui/controller/AuthorizationController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
@RestController
2727
@RequiredArgsConstructor
2828
@Slf4j
29-
public class AccessController implements AuthorizationApi {
29+
public class AuthorizationController implements AuthorizationApi {
3030

3131
private final AccessControlService accessControlService;
3232

0 commit comments

Comments
 (0)