diff --git a/README.md b/README.md
index d89043ddc..5a0932939 100644
--- a/README.md
+++ b/README.md
@@ -57,7 +57,9 @@ Only a curated list of the [vast amount](http://geoserver.org/release/stable/) o
- cog
- importer
- imagepyramid
-- gt-iau-wkt ([https://docs.geotools.org/latest/userguide/library/referencing/iau.html](IAU planetary CRS Plugin)(
+- [IAU planetary CRS Plugin](https://docs.geotools.org/latest/userguide/library/referencing/iau.html)
+- JDBC Security
+- LDAP Security
Advanced ACL system is available through the project [GeoServer ACL](https://github.com/geoserver/geoserver-acl) which offers the same capacities as GeoFence.
diff --git a/src/apps/geoserver/webui/pom.xml b/src/apps/geoserver/webui/pom.xml
index d2588d2c5..1607b8aea 100644
--- a/src/apps/geoserver/webui/pom.xml
+++ b/src/apps/geoserver/webui/pom.xml
@@ -29,6 +29,14 @@
org.geoserver.web
gs-web-core
+
+ org.geoserver.web
+ gs-web-sec-jdbc
+
+
+ org.geoserver.web
+ gs-web-sec-ldap
+
org.geoserver.web
gs-web-wms
diff --git a/src/pom.xml b/src/pom.xml
index 8d890cf24..21021e7cb 100644
--- a/src/pom.xml
+++ b/src/pom.xml
@@ -413,6 +413,32 @@
gs-web-sec-core
${gs.version}
+
+ org.geoserver.security
+ gs-sec-jdbc
+ ${gs.version}
+
+
+ org.geoserver.web
+ gs-web-sec-jdbc
+ ${gs.version}
+
+
+ org.geoserver.security
+ gs-sec-ldap
+ ${gs.version}
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+
+
+
+
+ org.geoserver.web
+ gs-web-sec-ldap
+ ${gs.version}
+
org.geoserver
gs-rest
diff --git a/src/starters/security/pom.xml b/src/starters/security/pom.xml
index fd489d647..1e0da4d47 100644
--- a/src/starters/security/pom.xml
+++ b/src/starters/security/pom.xml
@@ -52,6 +52,24 @@
gs-web-sec-core
true
+
+ org.geoserver.security
+ gs-sec-jdbc
+
+
+ org.geoserver.web
+ gs-web-sec-jdbc
+ true
+
+
+ org.geoserver.security
+ gs-sec-ldap
+
+
+ org.geoserver.web
+ gs-web-sec-ldap
+ true
+
javax.servlet
diff --git a/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityAutoConfiguration.java b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityAutoConfiguration.java
new file mode 100644
index 000000000..9a0fed637
--- /dev/null
+++ b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityAutoConfiguration.java
@@ -0,0 +1,28 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.jdbc;
+
+import org.geoserver.cloud.autoconfigure.security.ConditionalOnGeoServerSecurityEnabled;
+import org.geoserver.cloud.autoconfigure.security.GeoServerSecurityAutoConfiguration;
+import org.geoserver.cloud.config.factory.FilteringXmlBeanDefinitionReader;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.ImportResource;
+
+/** {@link AutoConfiguration @AutoConfiguration} to enable {@code gs-sec-jdbc} */
+// run before GeoServerSecurityAutoConfiguration so the provider is available when
+// GeoServerSecurityManager calls GeoServerExtensions.extensions(GeoServerSecurityProvider.class)
+@AutoConfiguration(before = GeoServerSecurityAutoConfiguration.class)
+@EnableConfigurationProperties(JDBCSecurityConfigProperties.class)
+@ConditionalOnGeoServerSecurityEnabled
+@ConditionalOnProperty(
+ name = "geoserver.security.jdbc",
+ havingValue = "true",
+ matchIfMissing = true)
+@ImportResource(
+ reader = FilteringXmlBeanDefinitionReader.class, //
+ locations = "jar:gs-sec-jdbc-.*!/applicationContext.xml")
+public class JDBCSecurityAutoConfiguration {}
diff --git a/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityConfigProperties.java b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityConfigProperties.java
new file mode 100644
index 000000000..399e03f28
--- /dev/null
+++ b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityConfigProperties.java
@@ -0,0 +1,17 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.jdbc;
+
+import lombok.Data;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties("geoserver.security")
+@Data
+public class JDBCSecurityConfigProperties {
+
+ /** Enable or disable GeoServer JDBC Security plugin */
+ private boolean jdbc = true;
+}
diff --git a/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityWebUIAutoConfiguration.java b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityWebUIAutoConfiguration.java
new file mode 100644
index 000000000..34d089737
--- /dev/null
+++ b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityWebUIAutoConfiguration.java
@@ -0,0 +1,34 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.jdbc;
+
+import org.geoserver.cloud.autoconfigure.security.ConditionalOnGeoServerSecurityEnabled;
+import org.geoserver.cloud.autoconfigure.security.GeoServerSecurityAutoConfiguration;
+import org.geoserver.cloud.config.factory.FilteringXmlBeanDefinitionReader;
+import org.geoserver.security.web.auth.AuthenticationFilterPanelInfo;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.ImportResource;
+
+/**
+ * {@link AutoConfiguration @AutoConfiguration} to enable {@code gs-web-sec-jdbc} when running with
+ * the webui components in the classpath
+ */
+// run before GeoServerSecurityAutoConfiguration so the provider is available when
+// GeoServerSecurityManager calls GeoServerExtensions.extensions(GeoServerSecurityProvider.class)
+@AutoConfiguration(before = GeoServerSecurityAutoConfiguration.class)
+@EnableConfigurationProperties(JDBCSecurityConfigProperties.class)
+@ConditionalOnClass(AuthenticationFilterPanelInfo.class)
+@ConditionalOnGeoServerSecurityEnabled
+@ConditionalOnProperty(
+ name = "geoserver.security.jdbc",
+ havingValue = "true",
+ matchIfMissing = true)
+@ImportResource(
+ reader = FilteringXmlBeanDefinitionReader.class, //
+ locations = "jar:gs-web-sec-jdbc-.*!/applicationContext.xml")
+public class JDBCSecurityWebUIAutoConfiguration {}
diff --git a/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityAutoConfiguration.java b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityAutoConfiguration.java
new file mode 100644
index 000000000..b9dbf9606
--- /dev/null
+++ b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityAutoConfiguration.java
@@ -0,0 +1,28 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.ldap;
+
+import org.geoserver.cloud.autoconfigure.security.ConditionalOnGeoServerSecurityEnabled;
+import org.geoserver.cloud.autoconfigure.security.GeoServerSecurityAutoConfiguration;
+import org.geoserver.cloud.config.factory.FilteringXmlBeanDefinitionReader;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.ImportResource;
+
+/** {@link AutoConfiguration @AutoConfiguration} to enable {@code gs-sec-ldap} */
+// run before GeoServerSecurityAutoConfiguration so the provider is available when
+// GeoServerSecurityManager calls GeoServerExtensions.extensions(GeoServerSecurityProvider.class)
+@AutoConfiguration(before = GeoServerSecurityAutoConfiguration.class)
+@EnableConfigurationProperties(LDAPSecurityConfigProperties.class)
+@ConditionalOnGeoServerSecurityEnabled
+@ConditionalOnProperty(
+ name = "geoserver.security.ldap",
+ havingValue = "true",
+ matchIfMissing = true)
+@ImportResource(
+ reader = FilteringXmlBeanDefinitionReader.class, //
+ locations = "jar:gs-sec-ldap-.*!/applicationContext.xml")
+public class LDAPSecurityAutoConfiguration {}
diff --git a/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityConfigProperties.java b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityConfigProperties.java
new file mode 100644
index 000000000..2f3a5a69b
--- /dev/null
+++ b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityConfigProperties.java
@@ -0,0 +1,17 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.ldap;
+
+import lombok.Data;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties("geoserver.security")
+@Data
+public class LDAPSecurityConfigProperties {
+
+ /** Enable or disable GeoServer LDAP Security plugin */
+ private boolean ldap = true;
+}
diff --git a/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityWebUIAutoConfiguration.java b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityWebUIAutoConfiguration.java
new file mode 100644
index 000000000..7d44f50ac
--- /dev/null
+++ b/src/starters/security/src/main/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityWebUIAutoConfiguration.java
@@ -0,0 +1,34 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.ldap;
+
+import org.geoserver.cloud.autoconfigure.security.ConditionalOnGeoServerSecurityEnabled;
+import org.geoserver.cloud.autoconfigure.security.GeoServerSecurityAutoConfiguration;
+import org.geoserver.cloud.config.factory.FilteringXmlBeanDefinitionReader;
+import org.geoserver.security.web.auth.AuthenticationFilterPanelInfo;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.ImportResource;
+
+/**
+ * {@link AutoConfiguration @AutoConfiguration} to enable {@code gs-web-sec-ldap} when running with
+ * the webui components in the classpath
+ */
+// run before GeoServerSecurityAutoConfiguration so the provider is available when
+// GeoServerSecurityManager calls GeoServerExtensions.extensions(GeoServerSecurityProvider.class)
+@AutoConfiguration(before = GeoServerSecurityAutoConfiguration.class)
+@EnableConfigurationProperties(LDAPSecurityConfigProperties.class)
+@ConditionalOnClass(AuthenticationFilterPanelInfo.class)
+@ConditionalOnGeoServerSecurityEnabled
+@ConditionalOnProperty(
+ name = "geoserver.security.ldap",
+ havingValue = "true",
+ matchIfMissing = true)
+@ImportResource(
+ reader = FilteringXmlBeanDefinitionReader.class, //
+ locations = "jar:gs-web-sec-ldap-.*!/applicationContext.xml")
+public class LDAPSecurityWebUIAutoConfiguration {}
diff --git a/src/starters/security/src/main/resources/META-INF/spring.factories b/src/starters/security/src/main/resources/META-INF/spring.factories
index 5d7f64f07..b0e890a29 100644
--- a/src/starters/security/src/main/resources/META-INF/spring.factories
+++ b/src/starters/security/src/main/resources/META-INF/spring.factories
@@ -1,4 +1,8 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.geoserver.cloud.autoconfigure.authzn.AuthKeyAutoConfiguration,\
org.geoserver.cloud.autoconfigure.authzn.GatewayPreAuthenticationAutoConfiguration,\
-org.geoserver.cloud.autoconfigure.authzn.GatewaySharedAuthenticationAutoConfiguration
\ No newline at end of file
+org.geoserver.cloud.autoconfigure.authzn.GatewaySharedAuthenticationAutoConfiguration,\
+org.geoserver.cloud.autoconfigure.security.jdbc.JDBCSecurityAutoConfiguration,\
+org.geoserver.cloud.autoconfigure.security.jdbc.JDBCSecurityWebUIAutoConfiguration,\
+org.geoserver.cloud.autoconfigure.security.ldap.LDAPSecurityAutoConfiguration,\
+org.geoserver.cloud.autoconfigure.security.ldap.LDAPSecurityWebUIAutoConfiguration
\ No newline at end of file
diff --git a/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityAutoConfigurationTest.java b/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityAutoConfigurationTest.java
new file mode 100644
index 000000000..15574c9e5
--- /dev/null
+++ b/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityAutoConfigurationTest.java
@@ -0,0 +1,46 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.jdbc;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.geoserver.security.GeoServerSecurityManager;
+import org.geoserver.security.jdbc.JDBCSecurityProvider;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
+
+class JDBCSecurityAutoConfigurationTest {
+
+ private WebApplicationContextRunner runner =
+ new WebApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(JDBCSecurityAutoConfiguration.class))
+ .withBean(
+ GeoServerSecurityManager.class,
+ () -> mock(GeoServerSecurityManager.class));
+
+ @Test
+ void testExpectedBeans() {
+ runner.run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .hasSingleBean(JDBCSecurityProvider.class)
+ .getBean(JDBCSecurityConfigProperties.class)
+ .hasFieldOrPropertyWithValue("jdbc", true));
+ }
+
+ @Test
+ void testDisabled() {
+ runner.withPropertyValues("geoserver.security.jdbc=false")
+ .run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .doesNotHaveBean(JDBCSecurityProvider.class)
+ .doesNotHaveBean(JDBCSecurityConfigProperties.class));
+ }
+}
diff --git a/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityWebUIAutoConfigurationTest.java b/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityWebUIAutoConfigurationTest.java
new file mode 100644
index 000000000..0177ef7a0
--- /dev/null
+++ b/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/jdbc/JDBCSecurityWebUIAutoConfigurationTest.java
@@ -0,0 +1,72 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.jdbc;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.geoserver.platform.ModuleStatusImpl;
+import org.geoserver.security.GeoServerSecurityManager;
+import org.geoserver.security.web.auth.AuthenticationFilterPanelInfo;
+import org.geoserver.security.web.jdbc.JDBCAuthProviderPanelInfo;
+import org.geoserver.security.web.jdbc.JDBCRoleServicePanelInfo;
+import org.geoserver.security.web.jdbc.JDBCUserGroupServicePanelInfo;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
+
+class JDBCSecurityWebUIAutoConfigurationTest {
+
+ private WebApplicationContextRunner runner =
+ new WebApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(
+ JDBCSecurityAutoConfiguration.class,
+ JDBCSecurityWebUIAutoConfiguration.class))
+ .withBean(
+ GeoServerSecurityManager.class,
+ () -> mock(GeoServerSecurityManager.class));
+
+ @Test
+ void testConditionalOnClassNoMatch() {
+ runner.withClassLoader(new FilteredClassLoader(AuthenticationFilterPanelInfo.class))
+ .run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .doesNotHaveBean(JDBCUserGroupServicePanelInfo.class)
+ .doesNotHaveBean(JDBCRoleServicePanelInfo.class)
+ .doesNotHaveBean(JDBCAuthProviderPanelInfo.class)
+ .doesNotHaveBean("jdbcSecurityWebExtension"));
+ }
+
+ @Test
+ void testConditionalOnClassMatch() {
+ runner.run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .hasSingleBean(JDBCUserGroupServicePanelInfo.class)
+ .hasSingleBean(JDBCRoleServicePanelInfo.class)
+ .hasSingleBean(JDBCAuthProviderPanelInfo.class)
+ .hasBean("jdbcSecurityWebExtension")
+ .getBean("jdbcSecurityWebExtension")
+ .isInstanceOf(ModuleStatusImpl.class));
+ }
+
+ @Test
+ void testDisabled() {
+ runner.withPropertyValues("geoserver.security.jdbc=false")
+ .run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .doesNotHaveBean(JDBCUserGroupServicePanelInfo.class)
+ .doesNotHaveBean(JDBCRoleServicePanelInfo.class)
+ .doesNotHaveBean(JDBCAuthProviderPanelInfo.class)
+ .doesNotHaveBean("jdbcSecurityWebExtension"));
+ }
+}
diff --git a/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityAutoConfigurationTest.java b/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityAutoConfigurationTest.java
new file mode 100644
index 000000000..b8eb8224b
--- /dev/null
+++ b/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityAutoConfigurationTest.java
@@ -0,0 +1,47 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.ldap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.geoserver.cloud.autoconfigure.security.jdbc.JDBCSecurityConfigProperties;
+import org.geoserver.security.GeoServerSecurityManager;
+import org.geoserver.security.ldap.LDAPSecurityProvider;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
+
+class LDAPSecurityAutoConfigurationTest {
+
+ private WebApplicationContextRunner runner =
+ new WebApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(LDAPSecurityAutoConfiguration.class))
+ .withBean(
+ GeoServerSecurityManager.class,
+ () -> mock(GeoServerSecurityManager.class));
+
+ @Test
+ void testExpectedBeans() {
+ runner.run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .hasSingleBean(LDAPSecurityProvider.class)
+ .getBean(LDAPSecurityConfigProperties.class)
+ .hasFieldOrPropertyWithValue("ldap", true));
+ }
+
+ @Test
+ void testDisabled() {
+ runner.withPropertyValues("geoserver.security.ldap=false")
+ .run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .doesNotHaveBean(LDAPSecurityProvider.class)
+ .doesNotHaveBean(JDBCSecurityConfigProperties.class));
+ }
+}
diff --git a/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityWebUIAutoConfigurationTest.java b/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityWebUIAutoConfigurationTest.java
new file mode 100644
index 000000000..490e43a18
--- /dev/null
+++ b/src/starters/security/src/test/java/org/geoserver/cloud/autoconfigure/security/ldap/LDAPSecurityWebUIAutoConfigurationTest.java
@@ -0,0 +1,72 @@
+/*
+ * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the
+ * GPL 2.0 license, available at the root application directory.
+ */
+package org.geoserver.cloud.autoconfigure.security.ldap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.geoserver.platform.ModuleStatusImpl;
+import org.geoserver.security.GeoServerSecurityManager;
+import org.geoserver.security.web.auth.AuthenticationFilterPanelInfo;
+import org.geoserver.web.security.ldap.LDAPAuthProviderPanelInfo;
+import org.geoserver.web.security.ldap.LDAPRoleServicePanelInfo;
+import org.geoserver.web.security.ldap.LDAPUserGroupServicePanelInfo;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
+
+class LDAPSecurityWebUIAutoConfigurationTest {
+
+ private WebApplicationContextRunner runner =
+ new WebApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(
+ LDAPSecurityAutoConfiguration.class,
+ LDAPSecurityWebUIAutoConfiguration.class))
+ .withBean(
+ GeoServerSecurityManager.class,
+ () -> mock(GeoServerSecurityManager.class));
+
+ @Test
+ void testConditionalOnClassNoMatch() {
+ runner.withClassLoader(new FilteredClassLoader(AuthenticationFilterPanelInfo.class))
+ .run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .doesNotHaveBean(LDAPUserGroupServicePanelInfo.class)
+ .doesNotHaveBean(LDAPRoleServicePanelInfo.class)
+ .doesNotHaveBean(LDAPAuthProviderPanelInfo.class)
+ .doesNotHaveBean("ldapSecurityWebExtension"));
+ }
+
+ @Test
+ void testConditionalOnClassMatch() {
+ runner.run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .hasSingleBean(LDAPUserGroupServicePanelInfo.class)
+ .hasSingleBean(LDAPRoleServicePanelInfo.class)
+ .hasSingleBean(LDAPAuthProviderPanelInfo.class)
+ .hasBean("ldapSecurityWebExtension")
+ .getBean("ldapSecurityWebExtension")
+ .isInstanceOf(ModuleStatusImpl.class));
+ }
+
+ @Test
+ void testDisabled() {
+ runner.withPropertyValues("geoserver.security.ldap=false")
+ .run(
+ context ->
+ assertThat(context)
+ .hasNotFailed()
+ .doesNotHaveBean(LDAPUserGroupServicePanelInfo.class)
+ .doesNotHaveBean(LDAPRoleServicePanelInfo.class)
+ .doesNotHaveBean(LDAPAuthProviderPanelInfo.class)
+ .doesNotHaveBean("ldapSecurityWebExtension"));
+ }
+}