Browse Source

Implement LDAP authentication (#1173)

* Sync container versions in examples

* Add ldap required dependencies

* Create a separate package for security configs

* Fix annoying checkstyle line length

* Refactor auth security configuration setup

* Implement ldap authentication. Closes #1023

* Review fixes

* Review fixes
Roman Zabaluev 3 years ago
parent
commit
e34520f6e9

+ 78 - 0
docker/auth-ldap.yaml

@@ -0,0 +1,78 @@
+---
+version: '2'
+services:
+
+  kafka-ui:
+    container_name: kafka-ui
+    image: provectuslabs/kafka-ui:latest
+    ports:
+      - 8080:8080
+    depends_on:
+      - zookeeper0
+      - kafka0
+      - schemaregistry0
+    environment:
+      KAFKA_CLUSTERS_0_NAME: local
+      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka0:29092
+      KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper0:2181
+      KAFKA_CLUSTERS_0_JMXPORT: 9997
+      KAFKA_CLUSTERS_0_SCHEMAREGISTRY: http://schemaregistry0:8085
+      KAFKA_CLUSTERS_0_KAFKACONNECT_0_NAME: first
+      KAFKA_CLUSTERS_0_KAFKACONNECT_0_ADDRESS: http://kafka-connect0:8083
+      KAFKA_CLUSTERS_1_NAME: secondLocal
+      KAFKA_CLUSTERS_1_BOOTSTRAPSERVERS: kafka1:29092
+      KAFKA_CLUSTERS_1_ZOOKEEPER: zookeeper1:2181
+      KAFKA_CLUSTERS_1_JMXPORT: 9998
+      KAFKA_CLUSTERS_1_SCHEMAREGISTRY: http://schemaregistry1:8085
+      KAFKA_CLUSTERS_1_KAFKACONNECT_0_NAME: first
+      KAFKA_CLUSTERS_1_KAFKACONNECT_0_ADDRESS: http://kafka-connect0:8083
+      AUTH_TYPE: "LDAP"
+      SPRING_LDAP_URLS: "ldap://ldap:10389"
+      SPRING_LDAP_DN_PATTERN: "cn={0},ou=people,dc=planetexpress,dc=com"
+
+  ldap:
+    image: rroemhild/test-openldap:latest
+    hostname: "ldap"
+
+  zookeeper0:
+    image: confluentinc/cp-zookeeper:5.2.4
+    environment:
+      ZOOKEEPER_CLIENT_PORT: 2181
+      ZOOKEEPER_TICK_TIME: 2000
+    ports:
+      - 2181:2181
+
+  kafka0:
+    image: confluentinc/cp-kafka:5.3.1
+    depends_on:
+      - zookeeper0
+    ports:
+      - 9092:9092
+      - 9997:9997
+    environment:
+      KAFKA_BROKER_ID: 1
+      KAFKA_ZOOKEEPER_CONNECT: zookeeper0:2181
+      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka0:29092,PLAINTEXT_HOST://localhost:9092
+      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
+      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
+      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
+      JMX_PORT: 9997
+      KAFKA_JMX_OPTS: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka0 -Dcom.sun.management.jmxremote.rmi.port=9997
+
+  schemaregistry0:
+    image: confluentinc/cp-schema-registry:5.5.0
+    ports:
+      - 8085:8085
+    depends_on:
+      - zookeeper0
+      - kafka0
+    environment:
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: PLAINTEXT://kafka0:29092
+      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: zookeeper0:2181
+      SCHEMA_REGISTRY_KAFKASTORE_SECURITY_PROTOCOL: PLAINTEXT
+      SCHEMA_REGISTRY_HOST_NAME: schemaregistry0
+      SCHEMA_REGISTRY_LISTENERS: http://schemaregistry0:8085
+
+      SCHEMA_REGISTRY_SCHEMA_REGISTRY_INTER_INSTANCE_PROTOCOL: "http"
+      SCHEMA_REGISTRY_LOG4J_ROOT_LOGLEVEL: INFO
+      SCHEMA_REGISTRY_KAFKASTORE_TOPIC: _schemas

+ 2 - 2
docker/kafka-cluster-sr-auth.yaml

@@ -11,7 +11,7 @@ services:
       - 2182:2181
 
   kafka1:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper1
     environment:
@@ -54,7 +54,7 @@ services:
       SCHEMA_REGISTRY_KAFKASTORE_TOPIC: _schemas
 
   kafka-init-topics:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     volumes:
        - ./message.json:/data/message.json
     depends_on:

+ 6 - 6
docker/kafka-clusters-only.yaml

@@ -11,7 +11,7 @@ services:
     - 2181:2181
 
   kafka0:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper0
     environment:
@@ -28,7 +28,7 @@ services:
       - 9997:9997
 
   kafka01:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper0
     environment:
@@ -53,7 +53,7 @@ services:
       - 2182:2181
 
   kafka1:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper1
     environment:
@@ -70,7 +70,7 @@ services:
       - 9998:9998 
 
   schemaregistry0:
-    image: confluentinc/cp-schema-registry:5.2.4
+    image: confluentinc/cp-schema-registry:5.5.0
     depends_on:
       - zookeeper0
       - kafka0
@@ -107,7 +107,7 @@ services:
       SCHEMA_REGISTRY_KAFKASTORE_TOPIC: _schemas
 
   kafka-connect0:
-    image: confluentinc/cp-kafka-connect:5.2.4
+    image: confluentinc/cp-kafka-connect:6.0.1
     ports:
       - 8083:8083
     depends_on:
@@ -133,7 +133,7 @@ services:
 
 
   kafka-init-topics:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     volumes:
        - ./message.json:/data/message.json
     depends_on:

+ 3 - 3
docker/kafka-ui-auth-context.yaml

@@ -16,7 +16,7 @@ services:
       KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper0:2181
       KAFKA_CLUSTERS_0_JMXPORT: 9997
       SERVER_SERVLET_CONTEXT_PATH: /kafkaui
-      AUTH_ENABLED: "true"
+      AUTH_TYPE: "LOGIN_FORM"
       SPRING_SECURITY_USER_NAME: admin
       SPRING_SECURITY_USER_PASSWORD: pass
 
@@ -29,7 +29,7 @@ services:
       - 2181:2181
 
   kafka0:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper0
     ports:
@@ -46,7 +46,7 @@ services:
       KAFKA_JMX_OPTS: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka0 -Dcom.sun.management.jmxremote.rmi.port=9997
 
   kafka-init-topics:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     volumes:
        - ./message.json:/data/message.json
     depends_on:

+ 4 - 4
docker/kafka-ui-connectors.yaml

@@ -38,7 +38,7 @@ services:
       - 2181:2181
 
   kafka0:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper0
     ports:
@@ -63,7 +63,7 @@ services:
       ZOOKEEPER_TICK_TIME: 2000
 
   kafka1:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper1
     ports:
@@ -82,7 +82,7 @@ services:
       KAFKA_JMX_OPTS: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka1 -Dcom.sun.management.jmxremote.rmi.port=9998
 
   schemaregistry0:
-    image: confluentinc/cp-schema-registry:5.2.4
+    image: confluentinc/cp-schema-registry:5.5.0
     ports:
       - 8085:8085
     depends_on:
@@ -148,7 +148,7 @@ services:
 #      AWS_SECRET_ACCESS_KEY: ""
 
   kafka-init-topics:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     volumes:
       - ./message.json:/data/message.json
     depends_on:

+ 3 - 3
docker/kafka-ui-jmx-secured.yml

@@ -81,7 +81,7 @@ services:
     - ./jmx/jmxremote.access:/jmx/jmxremote.access
 
   schemaregistry0:
-    image: confluentinc/cp-schema-registry:5.2.4
+    image: confluentinc/cp-schema-registry:5.5.0
     ports:
       - 8085:8085
     depends_on:
@@ -99,7 +99,7 @@ services:
       SCHEMA_REGISTRY_KAFKASTORE_TOPIC: _schemas
 
   kafka-connect0:
-    image: confluentinc/cp-kafka-connect:5.2.4
+    image: confluentinc/cp-kafka-connect:6.0.1
     ports:
       - 8083:8083
     depends_on:
@@ -124,7 +124,7 @@ services:
       CONNECT_PLUGIN_PATH: "/usr/share/java,/usr/share/confluent-hub-components"
 
   kafka-init-topics:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     volumes:
       - ./message.json:/data/message.json
     depends_on:

+ 4 - 4
docker/kafka-ui-zookeeper-ssl.yml

@@ -60,7 +60,7 @@ services:
       - 2182:2182
 
   kafka0:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper0
     ports:
@@ -89,7 +89,7 @@ services:
       KAFKA_ZOOKEEPER_SSL_TRUSTSTORE_TYPE: JKS
 
   schemaregistry0:
-    image: confluentinc/cp-schema-registry:5.2.4
+    image: confluentinc/cp-schema-registry:5.5.0
     ports:
       - 8085:8085
     depends_on:
@@ -107,7 +107,7 @@ services:
       SCHEMA_REGISTRY_KAFKASTORE_TOPIC: _schemas
 
   kafka-connect0:
-    image: confluentinc/cp-kafka-connect:5.2.4
+    image: confluentinc/cp-kafka-connect:6.0.1
     ports:
       - 8083:8083
     depends_on:
@@ -132,7 +132,7 @@ services:
       CONNECT_PLUGIN_PATH: "/usr/share/java,/usr/share/confluent-hub-components"
 
   kafka-init-topics:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     volumes:
       - ./message.json:/data/message.json
     depends_on:

+ 4 - 4
docker/kafka-ui.yaml

@@ -39,7 +39,7 @@ services:
       - 2181:2181
 
   kafka0:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper0
     ports:
@@ -62,7 +62,7 @@ services:
       ZOOKEEPER_TICK_TIME: 2000
 
   kafka1:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     depends_on:
       - zookeeper1
     ports:
@@ -79,7 +79,7 @@ services:
       KAFKA_JMX_OPTS: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka1 -Dcom.sun.management.jmxremote.rmi.port=9998
 
   schemaregistry0:
-    image: confluentinc/cp-schema-registry:5.2.4
+    image: confluentinc/cp-schema-registry:5.5.0
     ports:
       - 8085:8085
     depends_on:
@@ -140,7 +140,7 @@ services:
       CONNECT_PLUGIN_PATH: "/usr/share/java,/usr/share/confluent-hub-components"
 
   kafka-init-topics:
-    image: confluentinc/cp-kafka:5.2.4
+    image: confluentinc/cp-kafka:5.3.1
     volumes:
        - ./message.json:/data/message.json
     depends_on:

+ 1 - 1
etc/checkstyle/checkstyle.xml

@@ -42,7 +42,7 @@
 
     <module name="LineLength">
         <property name="fileExtensions" value="java"/>
-        <property name="max" value="100"/>
+        <property name="max" value="120"/>
         <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
     </module>
 

+ 4 - 5
guides/SSO.md

@@ -23,7 +23,7 @@ This is a main parameters required for enabling SSO
 #### Step 3
 To launch UI for Apache Kafka with enabled TLS and SSO run following:
 ``` bash
-docker run -p 8080:8080 -v `pwd`/cert:/opt/cert -e AUTH_ENABLED=true \
+docker run -p 8080:8080 -v `pwd`/cert:/opt/cert -e AUTH_TYPE=LOGIN_FORM \
   -e SECURITY_BASIC_ENABLED=true \
   -e SERVER_SSL_KEY_STORE_TYPE=PKCS12 \
   -e SERVER_SSL_KEY_STORE=/opt/cert/ui-for-apache-kafka.p12 \
@@ -35,16 +35,15 @@ docker run -p 8080:8080 -v `pwd`/cert:/opt/cert -e AUTH_ENABLED=true \
   -e SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_AUTH0_ISSUER_URI=https://dev-a63ggcut.auth0.com/ \
   -e TRUST_STORE=/opt/cert/ui-for-apache-kafka.p12 \
   -e TRUST_STORE_PASSWORD=123456 \
-provectuslabs/kafka-ui:0.1.0
+provectuslabs/kafka-ui:latest
 ```
 In the case with trusted CA-signed SSL certificate and SSL termination somewhere outside of application we can pass only SSO related environment variables:
 ``` bash
-docker run -p 8080:8080 -v `pwd`/cert:/opt/cert -e AUTH_ENABLED=true \
-  -e SECURITY_BASIC_ENABLED=true \
+docker run -p 8080:8080 -v `pwd`/cert:/opt/cert -e AUTH_TYPE=OAUTH2 \
   -e SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_AUTH0_CLIENTID=uhvaPKIHU4ZF8Ne4B6PGvF0hWW6OcUSB \
   -e SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_AUTH0_CLIENTSECRET=YXfRjmodifiedTujnkVr7zuW9ECCAK4TcnCio-i \
   -e SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_AUTH0_ISSUER_URI=https://dev-a63ggcut.auth0.com/ \
-provectuslabs/kafka-ui:0.1.0
+provectuslabs/kafka-ui:latest
 ```
 
 #### Step 4 (optional)

+ 10 - 0
kafka-ui-api/pom.xml

@@ -192,6 +192,16 @@
             <artifactId>antlr4-runtime</artifactId>
             <version>${antlr4-maven-plugin.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-ldap</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-ldap</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 0 - 24
kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/SecurityConfig.java

@@ -1,24 +0,0 @@
-package com.provectus.kafka.ui.config;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
-import org.springframework.security.config.web.server.ServerHttpSecurity;
-import org.springframework.security.web.server.SecurityWebFilterChain;
-
-@Configuration
-@EnableWebFluxSecurity
-@ConditionalOnProperty(value = "auth.enabled", havingValue = "false")
-public class SecurityConfig {
-
-  @Bean
-  public SecurityWebFilterChain configure(ServerHttpSecurity http) {
-    return http.authorizeExchange()
-        .anyExchange().permitAll()
-        .and()
-        .csrf().disable()
-        .build();
-  }
-
-}

+ 18 - 0
kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/AbstractAuthSecurityConfig.java

@@ -0,0 +1,18 @@
+package com.provectus.kafka.ui.config.auth;
+
+abstract class AbstractAuthSecurityConfig {
+
+  public static final String[] AUTH_WHITELIST = {
+      "/css/**",
+      "/js/**",
+      "/media/**",
+      "/resources/**",
+      "/actuator/health",
+      "/actuator/info",
+      "/auth",
+      "/login",
+      "/logout",
+      "/oauth2/**"
+  };
+
+}

+ 40 - 0
kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/BasicAuthSecurityConfig.java

@@ -0,0 +1,40 @@
+package com.provectus.kafka.ui.config.auth;
+
+import com.provectus.kafka.ui.util.EmptyRedirectStrategy;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.web.server.SecurityWebFilterChain;
+import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
+
+@Configuration
+@EnableWebFluxSecurity
+@ConditionalOnProperty(value = "auth.type", havingValue = "LOGIN_FORM")
+@Log4j2
+public class BasicAuthSecurityConfig extends AbstractAuthSecurityConfig {
+
+  @Bean
+  public SecurityWebFilterChain configure(ServerHttpSecurity http) {
+    log.info("Configuring LOGIN_FORM authentication.");
+    http.authorizeExchange()
+        .pathMatchers(AUTH_WHITELIST)
+        .permitAll()
+        .anyExchange()
+        .authenticated();
+
+    final RedirectServerAuthenticationSuccessHandler handler = new RedirectServerAuthenticationSuccessHandler();
+    handler.setRedirectStrategy(new EmptyRedirectStrategy());
+
+    http
+        .httpBasic().and()
+        .formLogin()
+        .loginPage("/auth")
+        .authenticationSuccessHandler(handler);
+
+    return http.csrf().disable().build();
+  }
+
+}

+ 37 - 0
kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/DisabledAuthSecurityConfig.java

@@ -0,0 +1,37 @@
+package com.provectus.kafka.ui.config.auth;
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.web.server.SecurityWebFilterChain;
+
+@Configuration
+@EnableWebFluxSecurity
+@ConditionalOnProperty(value = "auth.type", havingValue = "DISABLED")
+@Log4j2
+public class DisabledAuthSecurityConfig extends AbstractAuthSecurityConfig {
+
+  @Bean
+  public SecurityWebFilterChain configure(ServerHttpSecurity http, Environment env, ApplicationContext context) {
+    if (env.getProperty("auth.enabled") != null) {
+      log.error("A deprecated property (auth.enabled) is present. "
+          + "Please replace it with 'auth.type' (possible values are: 'LOGIN_FORM', 'DISABLED', 'OAUTH2', 'LDAP') "
+          + "and restart the application.");
+      SpringApplication.exit(context, () -> 1);
+      System.exit(1);
+    }
+    log.warn("Authentication is disabled. Access will be unrestricted.");
+    return http.authorizeExchange()
+        .anyExchange().permitAll()
+        .and()
+        .csrf().disable()
+        .build();
+  }
+
+}

+ 69 - 0
kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/LdapSecurityConfig.java

@@ -0,0 +1,69 @@
+package com.provectus.kafka.ui.config.auth;
+
+import java.util.List;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.ldap.core.support.BaseLdapPathContextSource;
+import org.springframework.ldap.core.support.LdapContextSource;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.authentication.ReactiveAuthenticationManager;
+import org.springframework.security.authentication.ReactiveAuthenticationManagerAdapter;
+import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.ldap.authentication.BindAuthenticator;
+import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
+import org.springframework.security.web.server.SecurityWebFilterChain;
+
+@Configuration
+@EnableWebFluxSecurity
+@ConditionalOnProperty(value = "auth.type", havingValue = "LDAP")
+@Log4j2
+public class LdapSecurityConfig extends AbstractAuthSecurityConfig {
+
+  @Value("${spring.ldap.urls}")
+  private String ldapUrls;
+  @Value("${spring.ldap.dn.pattern}")
+  private String ldapUserDnPattern;
+
+  @Bean
+  public ReactiveAuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
+    BindAuthenticator ba = new BindAuthenticator(contextSource);
+    ba.setUserDnPatterns(new String[]{ldapUserDnPattern});
+
+    LdapAuthenticationProvider lap = new LdapAuthenticationProvider(ba);
+
+    AuthenticationManager am = new ProviderManager(List.of(lap));
+
+    return new ReactiveAuthenticationManagerAdapter(am);
+  }
+
+  @Bean
+  public BaseLdapPathContextSource contextSource() {
+    LdapContextSource ctx = new LdapContextSource();
+    ctx.setUrl(ldapUrls);
+    ctx.afterPropertiesSet();
+    return ctx;
+  }
+
+  @Bean
+  public SecurityWebFilterChain configureLdap(ServerHttpSecurity http) {
+    log.info("Configuring LDAP authentication.");
+
+    http
+        .authorizeExchange()
+        .pathMatchers(AUTH_WHITELIST)
+        .permitAll()
+        .anyExchange()
+        .authenticated()
+        .and()
+        .httpBasic();
+
+    return http.csrf().disable().build();
+  }
+
+}
+

+ 8 - 31
kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/OAuthSecurityConfig.java → kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/OAuthSecurityConfig.java

@@ -1,7 +1,7 @@
-package com.provectus.kafka.ui.config;
+package com.provectus.kafka.ui.config.auth;
 
-import com.provectus.kafka.ui.util.EmptyRedirectStrategy;
 import lombok.AllArgsConstructor;
+import lombok.extern.log4j.Log4j2;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
@@ -9,14 +9,14 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
 import org.springframework.security.config.web.server.ServerHttpSecurity;
 import org.springframework.security.web.server.SecurityWebFilterChain;
-import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
 import org.springframework.util.ClassUtils;
 
 @Configuration
 @EnableWebFluxSecurity
-@ConditionalOnProperty(value = "auth.enabled", havingValue = "true")
+@ConditionalOnProperty(value = "auth.type", havingValue = "OAUTH2")
 @AllArgsConstructor
-public class OAuthSecurityConfig {
+@Log4j2
+public class OAuthSecurityConfig extends AbstractAuthSecurityConfig {
 
   public static final String REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME =
       "org.springframework.security.oauth2.client.registration."
@@ -27,42 +27,19 @@ public class OAuthSecurityConfig {
       OAuthSecurityConfig.class.getClassLoader()
   );
 
-  private static final String[] AUTH_WHITELIST = {
-      "/css/**",
-      "/js/**",
-      "/media/**",
-      "/resources/**",
-      "/actuator/health",
-      "/actuator/info",
-      "/auth",
-      "/login",
-      "/logout",
-      "/oauth2/**"
-  };
-
   private final ApplicationContext context;
 
   @Bean
   public SecurityWebFilterChain configure(ServerHttpSecurity http) {
+    log.info("Configuring OAUTH2 authentication.");
     http.authorizeExchange()
-        .pathMatchers(
-            AUTH_WHITELIST
-        ).permitAll()
+        .pathMatchers(AUTH_WHITELIST)
+        .permitAll()
         .anyExchange()
         .authenticated();
 
     if (IS_OAUTH2_PRESENT && OAuth2ClasspathGuard.shouldConfigure(this.context)) {
       OAuth2ClasspathGuard.configure(this.context, http);
-    } else {
-      final RedirectServerAuthenticationSuccessHandler handler =
-          new RedirectServerAuthenticationSuccessHandler();
-      handler.setRedirectStrategy(new EmptyRedirectStrategy());
-
-      http
-          .httpBasic().and()
-          .formLogin()
-          .loginPage("/auth")
-          .authenticationSuccessHandler(handler);
     }
 
     return http.csrf().disable().build();

+ 1 - 1
kafka-ui-api/src/main/resources/application-gauth.yml

@@ -1,5 +1,5 @@
 auth:
-  enabled: true
+  type: OAUTH2
 spring:
   security:
     oauth2:

+ 1 - 1
kafka-ui-api/src/main/resources/application-local.yml

@@ -31,4 +31,4 @@ spring:
   jmx:
     enabled: true
 auth:
-  enabled: false
+  type: DISABLED

+ 4 - 3
kafka-ui-api/src/main/resources/application.yml

@@ -1,6 +1,6 @@
 auth:
-  enabled: false
-management:
+  type: DISABLED
+  management:
   endpoint:
     info:
       enabled: true
@@ -17,4 +17,5 @@ logging:
     com.provectus: DEBUG
     #org.springframework.http.codec.json.Jackson2JsonEncoder: DEBUG
     #org.springframework.http.codec.json.Jackson2JsonDecoder: DEBUG
-    reactor.netty.http.server.AccessLog: INFO
+    reactor.netty.http.server.AccessLog: INFO
+

+ 1 - 1
kafka-ui-api/src/test/resources/application-test.yml

@@ -10,4 +10,4 @@ spring:
   jmx:
     enabled: true
 auth:
-  enabled: false
+  type: DISABLED

+ 1 - 1
kafka-ui-react-app/docker-compose.yaml

@@ -27,7 +27,7 @@ services:
     restart: always
 
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:5.5.0
     hostname: schema-registry
     ports:
       - "8081:8081"