diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfiguration.java index 3d0670be3c..54e5ae5724 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfiguration.java @@ -26,6 +26,7 @@ import com.unboundid.ldap.listener.InMemoryDirectoryServer; import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; import com.unboundid.ldap.listener.InMemoryListenerConfig; import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.schema.Schema; import com.unboundid.ldif.LDIFReader; import org.springframework.boot.autoconfigure.AutoConfigureBefore; @@ -55,6 +56,7 @@ import org.springframework.util.StringUtils; * {@link EnableAutoConfiguration Auto-configuration} for Embedded LDAP. * * @author Eddú Meléndez + * @author Mathieu Ouellet * @since 1.5.0 */ @Configuration @@ -107,6 +109,24 @@ public class EmbeddedLdapAutoConfiguration { this.embeddedProperties.getCredential().getUsername(), this.embeddedProperties.getCredential().getPassword()); } + + if (!this.embeddedProperties.getValidation().isEnabled()) { + config.setSchema(null); + } + else { + Resource schema = this.embeddedProperties.getValidation().getSchema(); + if (schema != null) { + try { + config.setSchema(Schema.mergeSchemas(Schema.getDefaultStandardSchema(), + Schema.getSchema(schema.getInputStream()))); + } + catch (Exception ex) { + throw new IllegalStateException( + "Unable to load schema " + schema.getDescription(), ex); + } + } + } + InMemoryListenerConfig listenerConfig = InMemoryListenerConfig .createLDAPConfig("LDAP", this.embeddedProperties.getPort()); config.setListenerConfigs(listenerConfig); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapProperties.java index 1a4ac083ed..bd4de81fa3 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapProperties.java @@ -17,11 +17,13 @@ package org.springframework.boot.autoconfigure.ldap.embedded; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.core.io.Resource; /** * Configuration properties for Embedded LDAP. * * @author Eddú Meléndez + * @author Mathieu Ouellet * @since 1.5.0 */ @ConfigurationProperties(prefix = "spring.ldap.embedded") @@ -47,6 +49,11 @@ public class EmbeddedLdapProperties { */ private String ldif = "classpath:schema.ldif"; + /** + * Schema validation. + */ + private Validation validation = new Validation(); + public int getPort() { return this.port; } @@ -79,7 +86,11 @@ public class EmbeddedLdapProperties { this.ldif = ldif; } - static class Credential { + public Validation getValidation() { + return this.validation; + } + + public static class Credential { /** * Embedded LDAP username. @@ -109,4 +120,34 @@ public class EmbeddedLdapProperties { } + public static class Validation { + + /** + * Enable LDAP schema validation. + */ + private boolean enabled = true; + + /** + * Path to the custom schema. + */ + private Resource schema; + + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public Resource getSchema() { + return this.schema; + } + + public void setSchema(Resource schema) { + this.schema = schema; + } + + } + } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfigurationTests.java index d5d5e54dae..5643eda946 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfigurationTests.java @@ -131,6 +131,29 @@ public class EmbeddedLdapAutoConfigurationTests { assertThat(ldapTemplate.list("ou=company1,c=Sweden,dc=spring,dc=org")).hasSize(4); } + @Test + public void testDisableSchemaValidation() throws LDAPException { + load("spring.ldap.embedded.validation.enabled:false", + "spring.ldap.embedded.base-dn:dc=spring,dc=org"); + InMemoryDirectoryServer server = this.context + .getBean(InMemoryDirectoryServer.class); + assertThat(server.getSchema()).isNull(); + } + + @Test + public void testCustomSchemaValidation() throws LDAPException { + load("spring.ldap.embedded.validation.schema:classpath:custom-schema.ldif", + "spring.ldap.embedded.ldif:classpath:custom-schema-sample.ldif", + "spring.ldap.embedded.base-dn:dc=spring,dc=org"); + InMemoryDirectoryServer server = this.context + .getBean(InMemoryDirectoryServer.class); + + assertThat(server.getSchema().getObjectClass("exampleAuxiliaryClass")) + .isNotNull(); + assertThat(server.getSchema().getAttributeType("exampleAttributeName")) + .isNotNull(); + } + private void load(String... properties) { EnvironmentTestUtils.addEnvironment(this.context, properties); this.context.register(EmbeddedLdapAutoConfiguration.class, diff --git a/spring-boot-autoconfigure/src/test/resources/custom-schema-sample.ldif b/spring-boot-autoconfigure/src/test/resources/custom-schema-sample.ldif new file mode 100644 index 0000000000..c5b81e84ce --- /dev/null +++ b/spring-boot-autoconfigure/src/test/resources/custom-schema-sample.ldif @@ -0,0 +1,7 @@ +dn: dc=spring,dc=org +objectclass: top +objectclass: domain +objectclass: extensibleObject +objectClass: exampleAuxiliaryClass +dc: spring +exampleAttributeName: exampleAttributeName diff --git a/spring-boot-autoconfigure/src/test/resources/custom-schema.ldif b/spring-boot-autoconfigure/src/test/resources/custom-schema.ldif new file mode 100644 index 0000000000..a561a201cb --- /dev/null +++ b/spring-boot-autoconfigure/src/test/resources/custom-schema.ldif @@ -0,0 +1,17 @@ +dn: cn=schema +attributeTypes: ( 1.3.6.1.4.1.32473.1.1.1 + NAME 'exampleAttributeName' + DESC 'An example attribute type definition' + EQUALITY caseIgnoreMatch + ORDERING caseIgnoreOrderingMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + X-ORIGIN 'Managing Schema Document' ) +objectClasses: ( 1.3.6.1.4.1.32473.1.2.2 + NAME 'exampleAuxiliaryClass' + DESC 'An example auxiliary object class definition' + SUP top + AUXILIARY + MAY exampleAttributeName + X-ORIGIN 'Managing Schema Document' ) \ No newline at end of file diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 069b24e757..9adba7f721 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -323,11 +323,13 @@ content into your application; rather pick only the properties that you need. spring.ldap.base-environment.*= # LDAP specification settings. # EMBEDDED LDAP ({sc-spring-boot-autoconfigure}/ldap/embedded/EmbeddedLdapProperties.{sc-ext}[EmbeddedLdapProperties]) - spring.ldap.embedded.port= # Embedded LDAP port. + spring.ldap.embedded.base-dn= # The base DN spring.ldap.embedded.credential.username= # Embedded LDAP username. spring.ldap.embedded.credential.password= # Embedded LDAP password. - spring.ldap.embedded.base-dn= # The base DN spring.ldap.embedded.ldif=classpath:schema.ldif # Schema (LDIF) script resource reference. + spring.ldap.embedded.port= # Embedded LDAP port. + spring.ldap.embedded.validation.enabled=true # Enable LDAP schema validation. + spring.ldap.embedded.validation.schema= # Path to the custom schema. # SPRING MOBILE DEVICE VIEWS ({sc-spring-boot-autoconfigure}/mobile/DeviceDelegatingViewResolverAutoConfiguration.{sc-ext}[DeviceDelegatingViewResolverAutoConfiguration]) spring.mobile.devicedelegatingviewresolver.enable-fallback=false # Enable support for fallback resolution. diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 561eafb7ee..ed1c8f6e26 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -3991,6 +3991,10 @@ If there is a `schema.ldif` file on your classpath it will be used to initialize server. You can also use the `spring.ldap.embedded.ldif` property if you want to load the initialization script from a different resource. +By default, a standard schema will be used to validate `LDIF` files, you can turn off +validation altogether using the `spring.ldap.embedded.validation.enabled` property. If +you have custom attributes, you can use `spring.ldap.embedded.validation.schema` to define +your custom attribute types or object classes. [[boot-features-caching]]