From 9b2af944fa925b73ec3a884b6456b3e06a3cece0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Wed, 7 Nov 2018 18:09:53 -0500 Subject: [PATCH 1/5] Add unbounid support in xml Currently, spring-security provides apacheds integration by default. This commit introduces a new `mode` in the `ldap-server` tag which allows to choose beetween `apacheds` and `unboundid`. In order to keep backward compatibility if `mode` is not set and apacheds jars are in the classpath apacheds is used as a embedded ldap. Fixes gh-6011 Currently, unboundid was added as a support for embbeded LDAP and it is used on the Java Config. This commit introduces support from XML side. Also, give the chance to users to move from apacheds to unboundid using a new attribute `mode`. Fixes gh-6011 --- config/spring-security-config.gradle | 1 + .../security/config/BeanIds.java | 2 + .../config/SecurityNamespaceHandler.java | 4 +- .../ldap/LdapServerBeanDefinitionParser.java | 115 ++++++++++++++++-- .../security/config/spring-security-5.2.rnc | 3 + .../security/config/spring-security-5.2.xsd | 67 ++++++---- .../LdapServerBeanDefinitionParserTest.java | 67 ++++++++++ .../util/InMemoryXmlApplicationContext.java | 5 +- .../servlet/additional-topics/ldap.adoc | 2 + .../_includes/servlet/appendix/namespace.adoc | 3 + docs/manual/src/docs/asciidoc/index.adoc | 2 +- 11 files changed, 229 insertions(+), 42 deletions(-) create mode 100644 config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java diff --git a/config/spring-security-config.gradle b/config/spring-security-config.gradle index 580a2bdbc2..ede301e05b 100644 --- a/config/spring-security-config.gradle +++ b/config/spring-security-config.gradle @@ -71,6 +71,7 @@ dependencies { testRuntime 'cglib:cglib-nodep' testRuntime 'org.hsqldb:hsqldb' + testCompile "com.unboundid:unboundid-ldapsdk" } diff --git a/config/src/main/java/org/springframework/security/config/BeanIds.java b/config/src/main/java/org/springframework/security/config/BeanIds.java index 5b9cd0109f..85027d2c73 100644 --- a/config/src/main/java/org/springframework/security/config/BeanIds.java +++ b/config/src/main/java/org/springframework/security/config/BeanIds.java @@ -53,6 +53,8 @@ public abstract class BeanIds { + "methodSecurityMetadataSourceAdvisor"; public static final String EMBEDDED_APACHE_DS = PREFIX + "apacheDirectoryServerContainer"; + public static final String EMBEDDED_UNBOUNDID = PREFIX + + "unboundidServerContainer"; public static final String CONTEXT_SOURCE = PREFIX + "securityContextSource"; public static final String DEBUG_FILTER = PREFIX + "debugFilter"; diff --git a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java index bb6a5dd3fd..02ff0a4505 100644 --- a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java +++ b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java @@ -86,7 +86,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { if (!namespaceMatchesVersion(element)) { pc.getReaderContext() .fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema " - + "with Spring Security 4.2. Please update your schema declarations to the 4.2 schema.", + + "with Spring Security 5.2. Please update your schema declarations to the 5.2 schema.", element); } String name = pc.getDelegate().getLocalName(element); @@ -221,7 +221,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { private boolean matchesVersionInternal(Element element) { String schemaLocation = element.getAttributeNS( "http://www.w3.org/2001/XMLSchema-instance", "schemaLocation"); - return schemaLocation.matches("(?m).*spring-security-4\\.2.*.xsd.*") + return schemaLocation.matches("(?m).*spring-security-5\\.2.*.xsd.*") || schemaLocation.matches("(?m).*spring-security.xsd.*") || !schemaLocation.matches("(?m).*spring-security.*"); } diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java index 9111af1654..f1f1342714 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,13 @@ package org.springframework.security.config.ldap; import java.io.IOException; import java.net.ServerSocket; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; @@ -28,11 +32,14 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.config.BeanIds; import org.springframework.security.ldap.server.ApacheDSContainer; +import org.springframework.security.ldap.server.UnboundIdContainer; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * @author Luke Taylor + * @author Eddú Meléndez */ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { private static final String CONTEXT_SOURCE_CLASS = "org.springframework.security.ldap.DefaultSpringSecurityContextSource"; @@ -65,6 +72,22 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { private static final int DEFAULT_PORT = 33389; public static final String OPT_DEFAULT_PORT = String.valueOf(DEFAULT_PORT); + private static final String APACHEDS_CLASSNAME = "org.apache.directory.server.core.DefaultDirectoryService"; + private static final String UNBOUNID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer"; + + private static final String APACHEDS_CONTAINER_CLASSNAME = "org.springframework.security.ldap.server.ApacheDSContainer"; + private static final String UNBOUNDID_CONTAINER_CLASSNAME = "org.springframework.security.ldap.server.UnboundIdContainer"; + + private Map embeddedServers; + + public LdapServerBeanDefinitionParser() { + Map embeddedLdapServers = new HashMap<>(); + embeddedLdapServers.put("apacheds", new EmbeddedLdapServer(BeanIds.EMBEDDED_APACHE_DS, APACHEDS_CLASSNAME, APACHEDS_CONTAINER_CLASSNAME)); + embeddedLdapServers.put("unboundid", new EmbeddedLdapServer(BeanIds.EMBEDDED_UNBOUNDID, UNBOUNID_CLASSNAME, UNBOUNDID_CONTAINER_CLASSNAME)); + + this.embeddedServers = Collections.unmodifiableMap(embeddedLdapServers); + } + public BeanDefinition parse(Element elt, ParserContext parserContext) { String url = elt.getAttribute(ATT_URL); @@ -114,6 +137,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { * @return the BeanDefinition for the ContextSource for the embedded server. * * @see ApacheDSContainer + * @see UnboundIdContainer */ private RootBeanDefinition createEmbeddedServer(Element element, ParserContext parserContext) { @@ -142,34 +166,78 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { contextSource.addPropertyValue("userDn", "uid=admin,ou=system"); contextSource.addPropertyValue("password", "secret"); - RootBeanDefinition apacheContainer = new RootBeanDefinition( - "org.springframework.security.ldap.server.ApacheDSContainer", null, null); - apacheContainer.setSource(source); - apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(suffix); + String mode = element.getAttribute("mode"); + RootBeanDefinition ldapContainer = getRootBeanDefinition(mode); + ldapContainer.setSource(source); + ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(suffix); String ldifs = element.getAttribute(ATT_LDIF_FILE); if (!StringUtils.hasText(ldifs)) { ldifs = OPT_DEFAULT_LDIF_FILE; } - apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs); - apacheContainer.getPropertyValues().addPropertyValue("port", port); + ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs); + ldapContainer.getPropertyValues().addPropertyValue("port", port); logger.info("Embedded LDAP server bean definition created for URL: " + url); if (parserContext.getRegistry() - .containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS)) { + .containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS) || + parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_UNBOUNDID)) { parserContext.getReaderContext().error( "Only one embedded server bean is allowed per application context", element); } - parserContext.getRegistry().registerBeanDefinition(BeanIds.EMBEDDED_APACHE_DS, - apacheContainer); + EmbeddedLdapServer embeddedLdapServer = resolveEmbeddedLdapServer(mode); + if (embeddedLdapServer != null) { + parserContext.getRegistry().registerBeanDefinition(embeddedLdapServer.getBeanId(), + ldapContainer); + } return (RootBeanDefinition) contextSource.getBeanDefinition(); } + private RootBeanDefinition getRootBeanDefinition(String mode) { + if (StringUtils.hasLength(mode)) { + if (isEmbeddedServerEnabled(mode)) { + return new RootBeanDefinition(this.embeddedServers.get(mode).getContainerClass(), null, null); + } + } + else { + for (Map.Entry entry : this.embeddedServers.entrySet()) { + EmbeddedLdapServer ldapServer = entry.getValue(); + if (ClassUtils.isPresent(ldapServer.getClassName(), getClass().getClassLoader())) { + return new RootBeanDefinition(ldapServer.getContainerClass(), null, null); + } + } + } + throw new IllegalStateException("Embedded LDAP server is not provided"); + } + + private boolean isEmbeddedServerEnabled(String mode) { + EmbeddedLdapServer server = resolveEmbeddedLdapServer(mode); + return server != null; + } + + private EmbeddedLdapServer resolveEmbeddedLdapServer(String mode) { + if (StringUtils.hasLength(mode)) { + if (this.embeddedServers.containsKey(mode) || + ClassUtils.isPresent(this.embeddedServers.get(mode).getClassName(), getClass().getClassLoader())) { + return this.embeddedServers.get(mode); + } + } + else { + for (Map.Entry entry : this.embeddedServers.entrySet()) { + EmbeddedLdapServer ldapServer = entry.getValue(); + if (ClassUtils.isPresent(ldapServer.getClassName(), getClass().getClassLoader())) { + return ldapServer; + } + } + } + return null; + } + private String getDefaultPort() { ServerSocket serverSocket = null; try { @@ -196,4 +264,31 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { } } } + + private class EmbeddedLdapServer { + + private String beanId; + + private String className; + + private String containerClass; + + public EmbeddedLdapServer(String beanId, String className, String containerClass) { + this.beanId = beanId; + this.className = className; + this.containerClass = containerClass; + } + + public String getBeanId() { + return this.beanId; + } + + public String getClassName() { + return this.className; + } + + public String getContainerClass() { + return this.containerClass; + } + } } diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc index 1e82f6acbd..f35432862e 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc @@ -83,6 +83,9 @@ ldap-server.attlist &= ldap-server.attlist &= ## Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" attribute root { xsd:string }? +ldap-server.attlist &= + ## Explicitly specifies which embedded ldap server should use. Values are `apacheds` and `unboundid`. By default, it will depends if the library is available in the classpath. + attribute mode { "apacheds" | "unboundid" }? ldap-server-ref-attribute = ## The optional server to use. If omitted, and a default LDAP server is registered (using with no Id), that server will be used. diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd index 410ddc14c6..7e0e81d244 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd @@ -124,7 +124,7 @@ - + @@ -222,6 +222,19 @@ + + + Explicitly specifies which embedded ldap server should use. Values are `apacheds` and + `unboundid`. By default, it will depends if the library is available in the classpath. + + + + + + + + + @@ -395,7 +408,7 @@ - + @@ -475,7 +488,7 @@ - + @@ -528,7 +541,7 @@ - + @@ -772,13 +785,13 @@ - - - - - - - + + + + + + + @@ -1220,7 +1233,7 @@ - + @@ -1245,7 +1258,7 @@ - + @@ -1302,7 +1315,7 @@ - + @@ -1349,7 +1362,7 @@ - + @@ -1437,7 +1450,7 @@ - + Sets up an attribute exchange configuration to request specified attributes from the @@ -1636,7 +1649,7 @@ - + @@ -1652,7 +1665,7 @@ - + @@ -1708,7 +1721,7 @@ - + @@ -1755,7 +1768,7 @@ - + @@ -1853,7 +1866,7 @@ - + @@ -1886,8 +1899,8 @@ - - + + @@ -1904,7 +1917,7 @@ - + @@ -2041,7 +2054,7 @@ - + @@ -2093,7 +2106,7 @@ - + @@ -2730,4 +2743,4 @@ - \ No newline at end of file + diff --git a/config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java b/config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java new file mode 100644 index 0000000000..9c5d3eefba --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.ldap; + +import org.junit.After; +import org.junit.Test; + +import org.springframework.security.config.BeanIds; +import org.springframework.security.config.util.InMemoryXmlApplicationContext; +import org.springframework.security.ldap.server.ApacheDSContainer; +import org.springframework.security.ldap.server.UnboundIdContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Eddú Meléndez + */ +public class LdapServerBeanDefinitionParserTest { + + private InMemoryXmlApplicationContext context; + + @After + public void closeAppContext() { + if (this.context != null) { + this.context.close(); + this.context = null; + } + } + + @Test + public void apacheDirectoryServerIsStartedByDefault() { + this.context = new InMemoryXmlApplicationContext("", "5.2", null); + String[] beanNames = this.context.getBeanNamesForType(ApacheDSContainer.class); + assertThat(beanNames).hasSize(1); + assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_APACHE_DS); + } + + @Test + public void apacheDirectoryServerIsStartedWhenIsSet() { + this.context = new InMemoryXmlApplicationContext("", "5.2", null); + String[] beanNames = this.context.getBeanNamesForType(ApacheDSContainer.class); + assertThat(beanNames).hasSize(1); + assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_APACHE_DS); + } + + @Test + public void unboundidIsStartedWhenModeIsSet() { + this.context = new InMemoryXmlApplicationContext("", "5.2", null); + String[] beanNames = this.context.getBeanNamesForType(UnboundIdContainer.class); + assertThat(beanNames).hasSize(1); + assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_UNBOUNDID); + } +} diff --git a/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java b/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java index 4336af0cc8..4b7ac18d8a 100644 --- a/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java +++ b/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2013 the original author or authors. + * Copyright 2009-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import org.springframework.security.util.InMemoryResource; /** * @author Luke Taylor + * @author Eddú Meléndez */ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext { static final String BEANS_OPENING = " ---- +NOTE: `spring-security` provides integration with `apacheds` and `unboundid` as a embedded ldap servers. You can choose between them using the attribute `mode` in `ldap-server`. + ==== Using an Embedded Test Server The `` element can also be used to create an embedded server, which can be very useful for testing and demonstrations. In this case you use it without the `url` attribute: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc index 67c96202c5..88fa302c0e 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc @@ -2360,6 +2360,9 @@ This is actually the bean `id` of the `ContextSource` instance, if you want to u [[nsa-ldap-server-attributes]] ===== Attributes +[[nsa-ldap-server-mode]] +* **mode** +Explicitly specifies which embedded ldap server should use. Values are `apacheds` and `unboundid`. By default, it will depends if the library is available in the classpath. [[nsa-ldap-server-id]] * **id** diff --git a/docs/manual/src/docs/asciidoc/index.adoc b/docs/manual/src/docs/asciidoc/index.adoc index 237c691546..9ffe2c96e1 100644 --- a/docs/manual/src/docs/asciidoc/index.adoc +++ b/docs/manual/src/docs/asciidoc/index.adoc @@ -1,5 +1,5 @@ = Spring Security Reference -Ben Alex; Luke Taylor; Rob Winch; Gunnar Hillert; Joe Grandja; Jay Bryant +Ben Alex; Luke Taylor; Rob Winch; Gunnar Hillert; Joe Grandja; Jay Bryant; Eddú Meléndez :include-dir: _includes :security-api-url: https://docs.spring.io/spring-security/site/docs/current/api/ :source-indent: 0 From 3511c0ea4f4f2d3cb1f15677aaec24a00ba01173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Tue, 13 Aug 2019 20:17:51 -0500 Subject: [PATCH 2/5] Update xsd --- .../security/config/spring-security-5.2.rnc | 2 +- .../security/config/spring-security-5.2.xsd | 58 +++++++++---------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc index f35432862e..745da4bbed 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc @@ -84,7 +84,7 @@ ldap-server.attlist &= ## Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" attribute root { xsd:string }? ldap-server.attlist &= - ## Explicitly specifies which embedded ldap server should use. Values are `apacheds` and `unboundid`. By default, it will depends if the library is available in the classpath. + ## Explicitly specifies which embedded ldap server should use. Values are 'apacheds' and 'unboundid'. By default, it will depends if the library is available in the classpath. attribute mode { "apacheds" | "unboundid" }? ldap-server-ref-attribute = diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd index 7e0e81d244..17ef4317c1 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd @@ -124,7 +124,7 @@ - + @@ -224,8 +224,8 @@ - Explicitly specifies which embedded ldap server should use. Values are `apacheds` and - `unboundid`. By default, it will depends if the library is available in the classpath. + Explicitly specifies which embedded ldap server should use. Values are 'apacheds' and + 'unboundid'. By default, it will depends if the library is available in the classpath. @@ -408,7 +408,7 @@ - + @@ -488,7 +488,7 @@ - + @@ -541,7 +541,7 @@ - + @@ -785,13 +785,13 @@ - - - - - - - + + + + + + + @@ -1233,7 +1233,7 @@ - + @@ -1258,7 +1258,7 @@ - + @@ -1315,7 +1315,7 @@ - + @@ -1362,7 +1362,7 @@ - + @@ -1450,7 +1450,7 @@ - + Sets up an attribute exchange configuration to request specified attributes from the @@ -1649,7 +1649,7 @@ - + @@ -1665,7 +1665,7 @@ - + @@ -1721,7 +1721,7 @@ - + @@ -1768,7 +1768,7 @@ - + @@ -1866,7 +1866,7 @@ - + @@ -1899,8 +1899,8 @@ - - + + @@ -1917,7 +1917,7 @@ - + @@ -2054,7 +2054,7 @@ - + @@ -2106,7 +2106,7 @@ - + @@ -2743,4 +2743,4 @@ - + \ No newline at end of file From c03fb701ce8d27d5c22fa50ba3dc3da211dfca3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Tue, 13 Aug 2019 20:36:15 -0500 Subject: [PATCH 3/5] Improve logic to pick embedded server --- .../ldap/LdapServerBeanDefinitionParser.java | 92 ++++--------------- .../LdapServerBeanDefinitionParserTest.java | 8 -- 2 files changed, 20 insertions(+), 80 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java index f1f1342714..a84ad1eb22 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java @@ -17,9 +17,6 @@ package org.springframework.security.config.ldap; import java.io.IOException; import java.net.ServerSocket; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -78,16 +75,6 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { private static final String APACHEDS_CONTAINER_CLASSNAME = "org.springframework.security.ldap.server.ApacheDSContainer"; private static final String UNBOUNDID_CONTAINER_CLASSNAME = "org.springframework.security.ldap.server.UnboundIdContainer"; - private Map embeddedServers; - - public LdapServerBeanDefinitionParser() { - Map embeddedLdapServers = new HashMap<>(); - embeddedLdapServers.put("apacheds", new EmbeddedLdapServer(BeanIds.EMBEDDED_APACHE_DS, APACHEDS_CLASSNAME, APACHEDS_CONTAINER_CLASSNAME)); - embeddedLdapServers.put("unboundid", new EmbeddedLdapServer(BeanIds.EMBEDDED_UNBOUNDID, UNBOUNID_CLASSNAME, UNBOUNDID_CONTAINER_CLASSNAME)); - - this.embeddedServers = Collections.unmodifiableMap(embeddedLdapServers); - } - public BeanDefinition parse(Element elt, ParserContext parserContext) { String url = elt.getAttribute(ATT_URL); @@ -189,55 +176,42 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { element); } - EmbeddedLdapServer embeddedLdapServer = resolveEmbeddedLdapServer(mode); - if (embeddedLdapServer != null) { - parserContext.getRegistry().registerBeanDefinition(embeddedLdapServer.getBeanId(), - ldapContainer); + String beanId = resolveBeanId(mode); + if (beanId != null) { + parserContext.getRegistry().registerBeanDefinition(beanId, ldapContainer); } return (RootBeanDefinition) contextSource.getBeanDefinition(); } private RootBeanDefinition getRootBeanDefinition(String mode) { - if (StringUtils.hasLength(mode)) { - if (isEmbeddedServerEnabled(mode)) { - return new RootBeanDefinition(this.embeddedServers.get(mode).getContainerClass(), null, null); - } + if (isApacheDsEnabled(mode)) { + return new RootBeanDefinition(APACHEDS_CONTAINER_CLASSNAME, null, null); } - else { - for (Map.Entry entry : this.embeddedServers.entrySet()) { - EmbeddedLdapServer ldapServer = entry.getValue(); - if (ClassUtils.isPresent(ldapServer.getClassName(), getClass().getClassLoader())) { - return new RootBeanDefinition(ldapServer.getContainerClass(), null, null); - } - } + else if (isUnboundidEnabled(mode)) { + return new RootBeanDefinition(UNBOUNDID_CONTAINER_CLASSNAME, null, null); } throw new IllegalStateException("Embedded LDAP server is not provided"); } - private boolean isEmbeddedServerEnabled(String mode) { - EmbeddedLdapServer server = resolveEmbeddedLdapServer(mode); - return server != null; - } - - private EmbeddedLdapServer resolveEmbeddedLdapServer(String mode) { - if (StringUtils.hasLength(mode)) { - if (this.embeddedServers.containsKey(mode) || - ClassUtils.isPresent(this.embeddedServers.get(mode).getClassName(), getClass().getClassLoader())) { - return this.embeddedServers.get(mode); - } + private String resolveBeanId(String mode) { + if (isApacheDsEnabled(mode)) { + return BeanIds.EMBEDDED_APACHE_DS; } - else { - for (Map.Entry entry : this.embeddedServers.entrySet()) { - EmbeddedLdapServer ldapServer = entry.getValue(); - if (ClassUtils.isPresent(ldapServer.getClassName(), getClass().getClassLoader())) { - return ldapServer; - } - } + else if (isUnboundidEnabled(mode)) { + return BeanIds.EMBEDDED_UNBOUNDID; } return null; } + private boolean isApacheDsEnabled(String mode) { + return "apacheds".equals(mode) || ClassUtils.isPresent(APACHEDS_CLASSNAME, getClass().getClassLoader()); + } + + private boolean isUnboundidEnabled(String mode) { + return "unboundid".equals(mode) || ClassUtils.isPresent(UNBOUNID_CLASSNAME, getClass().getClassLoader()); + } + private String getDefaultPort() { ServerSocket serverSocket = null; try { @@ -265,30 +239,4 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { } } - private class EmbeddedLdapServer { - - private String beanId; - - private String className; - - private String containerClass; - - public EmbeddedLdapServer(String beanId, String className, String containerClass) { - this.beanId = beanId; - this.className = className; - this.containerClass = containerClass; - } - - public String getBeanId() { - return this.beanId; - } - - public String getClassName() { - return this.className; - } - - public String getContainerClass() { - return this.containerClass; - } - } } diff --git a/config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java b/config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java index 9c5d3eefba..54e655e7f6 100644 --- a/config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java +++ b/config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java @@ -22,7 +22,6 @@ import org.junit.Test; import org.springframework.security.config.BeanIds; import org.springframework.security.config.util.InMemoryXmlApplicationContext; import org.springframework.security.ldap.server.ApacheDSContainer; -import org.springframework.security.ldap.server.UnboundIdContainer; import static org.assertj.core.api.Assertions.assertThat; @@ -57,11 +56,4 @@ public class LdapServerBeanDefinitionParserTest { assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_APACHE_DS); } - @Test - public void unboundidIsStartedWhenModeIsSet() { - this.context = new InMemoryXmlApplicationContext("", "5.2", null); - String[] beanNames = this.context.getBeanNamesForType(UnboundIdContainer.class); - assertThat(beanNames).hasSize(1); - assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_UNBOUNDID); - } } From 93142f3e3040c454fb933c2a92c5e4af0a0593cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Tue, 13 Aug 2019 20:39:25 -0500 Subject: [PATCH 4/5] Remove unboundid dependency --- config/spring-security-config.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/config/spring-security-config.gradle b/config/spring-security-config.gradle index ede301e05b..580a2bdbc2 100644 --- a/config/spring-security-config.gradle +++ b/config/spring-security-config.gradle @@ -71,7 +71,6 @@ dependencies { testRuntime 'cglib:cglib-nodep' testRuntime 'org.hsqldb:hsqldb' - testCompile "com.unboundid:unboundid-ldapsdk" } From 2e63def05b3f014b09604aa2ba1c866457a97be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Wed, 14 Aug 2019 00:56:26 -0500 Subject: [PATCH 5/5] Add tests --- .../main/resources/META-INF/spring.schemas | 4 +- .../util/InMemoryXmlApplicationContext.java | 2 +- ...test-ldap-embedded-apacheds-default.gradle | 13 ++++ .../LdapServerBeanDefinitionParserTests.java | 23 ++++--- .../resources/applicationContext-security.xml | 9 +++ .../src/integration-test/resources/users.ldif | 60 +++++++++++++++++++ ...y-itest-ldap-embedded-mode-apacheds.gradle | 13 ++++ .../LdapServerBeanDefinitionParserTests.java | 56 +++++++++++++++++ .../resources/applicationContext-security.xml | 9 +++ .../src/integration-test/resources/users.ldif | 60 +++++++++++++++++++ ...-itest-ldap-embedded-mode-unboundid.gradle | 13 ++++ .../LdapServerBeanDefinitionParserTests.java | 56 +++++++++++++++++ .../resources/applicationContext-security.xml | 9 +++ .../src/integration-test/resources/users.ldif | 60 +++++++++++++++++++ ...g-security-itest-ldap-embedded-none.gradle | 11 ++++ .../LdapServerBeanDefinitionParserTests.java | 53 ++++++++++++++++ .../resources/applicationContext-security.xml | 9 +++ .../src/integration-test/resources/users.ldif | 60 +++++++++++++++++++ ...est-ldap-embedded-unboundid-default.gradle | 13 ++++ .../LdapServerBeanDefinitionParserTests.java | 56 +++++++++++++++++ .../resources/applicationContext-security.xml | 9 +++ .../src/integration-test/resources/users.ldif | 60 +++++++++++++++++++ 22 files changed, 642 insertions(+), 16 deletions(-) create mode 100644 itest/ldap/embedded-ldap-apacheds-default/spring-security-itest-ldap-embedded-apacheds-default.gradle rename config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java => itest/ldap/embedded-ldap-apacheds-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java (62%) create mode 100644 itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/applicationContext-security.xml create mode 100644 itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/users.ldif create mode 100644 itest/ldap/embedded-ldap-mode-apacheds/spring-security-itest-ldap-embedded-mode-apacheds.gradle create mode 100644 itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java create mode 100644 itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/applicationContext-security.xml create mode 100644 itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/users.ldif create mode 100644 itest/ldap/embedded-ldap-mode-unboundid/spring-security-itest-ldap-embedded-mode-unboundid.gradle create mode 100644 itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java create mode 100644 itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/applicationContext-security.xml create mode 100644 itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/users.ldif create mode 100644 itest/ldap/embedded-ldap-none/spring-security-itest-ldap-embedded-none.gradle create mode 100644 itest/ldap/embedded-ldap-none/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java create mode 100644 itest/ldap/embedded-ldap-none/src/integration-test/resources/applicationContext-security.xml create mode 100644 itest/ldap/embedded-ldap-none/src/integration-test/resources/users.ldif create mode 100644 itest/ldap/embedded-ldap-unboundid-default/spring-security-itest-ldap-embedded-unboundid-default.gradle create mode 100644 itest/ldap/embedded-ldap-unboundid-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java create mode 100644 itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/applicationContext-security.xml create mode 100644 itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/users.ldif diff --git a/config/src/main/resources/META-INF/spring.schemas b/config/src/main/resources/META-INF/spring.schemas index e6197602a6..6efb761990 100644 --- a/config/src/main/resources/META-INF/spring.schemas +++ b/config/src/main/resources/META-INF/spring.schemas @@ -1,5 +1,5 @@ -http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.2.xsd -http\://www.springframework.org/schema/security/spring-security-5.2.xsd=org/springframework/security/config/spring-security-5.2.xsd +https\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.2.xsd +https\://www.springframework.org/schema/security/spring-security-5.2.xsd=org/springframework/security/config/spring-security-5.2.xsd http\://www.springframework.org/schema/security/spring-security-5.1.xsd=org/springframework/security/config/spring-security-5.1.xsd http\://www.springframework.org/schema/security/spring-security-5.0.xsd=org/springframework/security/config/spring-security-5.0.xsd http\://www.springframework.org/schema/security/spring-security-4.2.xsd=org/springframework/security/config/spring-security-4.2.xsd diff --git a/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java b/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java index 4b7ac18d8a..658369d6ca 100644 --- a/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java +++ b/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java @@ -38,7 +38,7 @@ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext + "http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd\n" + "http://www.springframework.org/schema/websocket https://www.springframework.org/schema/websocket/spring-websocket.xsd\n" + "http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-2.5.xsd\n" - + "http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-"; + + "http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security-"; static final String BEANS_CLOSE = "\n"; static final String SPRING_SECURITY_VERSION = "5.2"; diff --git a/itest/ldap/embedded-ldap-apacheds-default/spring-security-itest-ldap-embedded-apacheds-default.gradle b/itest/ldap/embedded-ldap-apacheds-default/spring-security-itest-ldap-embedded-apacheds-default.gradle new file mode 100644 index 0000000000..980de93e6b --- /dev/null +++ b/itest/ldap/embedded-ldap-apacheds-default/spring-security-itest-ldap-embedded-apacheds-default.gradle @@ -0,0 +1,13 @@ +apply plugin: 'io.spring.convention.spring-test' + +dependencies { + compile project(':spring-security-core') + compile 'org.springframework:spring-beans' + compile 'org.springframework:spring-context' + compile 'org.springframework:spring-core' + compile 'org.springframework:spring-tx' + compile project(':spring-security-config') + compile project(':spring-security-ldap') + + runtime apachedsDependencies +} diff --git a/config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java b/itest/ldap/embedded-ldap-apacheds-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java similarity index 62% rename from config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java rename to itest/ldap/embedded-ldap-apacheds-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java index 54e655e7f6..3898aea503 100644 --- a/config/src/test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTest.java +++ b/itest/ldap/embedded-ldap-apacheds-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package org.springframework.security.config.ldap; +package org.springframework.security; import org.junit.After; +import org.junit.Before; import org.junit.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.security.config.BeanIds; -import org.springframework.security.config.util.InMemoryXmlApplicationContext; import org.springframework.security.ldap.server.ApacheDSContainer; import static org.assertj.core.api.Assertions.assertThat; @@ -28,9 +29,14 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Eddú Meléndez */ -public class LdapServerBeanDefinitionParserTest { +public class LdapServerBeanDefinitionParserTests { - private InMemoryXmlApplicationContext context; + private ClassPathXmlApplicationContext context; + + @Before + public void setup() { + this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml"); + } @After public void closeAppContext() { @@ -42,15 +48,6 @@ public class LdapServerBeanDefinitionParserTest { @Test public void apacheDirectoryServerIsStartedByDefault() { - this.context = new InMemoryXmlApplicationContext("", "5.2", null); - String[] beanNames = this.context.getBeanNamesForType(ApacheDSContainer.class); - assertThat(beanNames).hasSize(1); - assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_APACHE_DS); - } - - @Test - public void apacheDirectoryServerIsStartedWhenIsSet() { - this.context = new InMemoryXmlApplicationContext("", "5.2", null); String[] beanNames = this.context.getBeanNamesForType(ApacheDSContainer.class); assertThat(beanNames).hasSize(1); assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_APACHE_DS); diff --git a/itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/applicationContext-security.xml b/itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/applicationContext-security.xml new file mode 100644 index 0000000000..da547d0b04 --- /dev/null +++ b/itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/applicationContext-security.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/users.ldif b/itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/users.ldif new file mode 100644 index 0000000000..222e03793c --- /dev/null +++ b/itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/users.ldif @@ -0,0 +1,60 @@ +dn: ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: ou=people,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: people + +dn: uid=rod,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Rod Johnson +sn: Johnson +uid: rod +userPassword: koala + +dn: uid=dianne,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Dianne Emu +sn: Emu +uid: dianne +userPassword: emu + +dn: uid=scott,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Scott +sn: Wombat +uid: scott +userPassword: wombat + +dn: cn=user,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: user +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org +member: uid=scott,ou=people,dc=springframework,dc=org + +dn: cn=teller,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: teller +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org + +dn: cn=supervisor,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: supervisor +member: uid=rod,ou=people,dc=springframework,dc=org diff --git a/itest/ldap/embedded-ldap-mode-apacheds/spring-security-itest-ldap-embedded-mode-apacheds.gradle b/itest/ldap/embedded-ldap-mode-apacheds/spring-security-itest-ldap-embedded-mode-apacheds.gradle new file mode 100644 index 0000000000..980de93e6b --- /dev/null +++ b/itest/ldap/embedded-ldap-mode-apacheds/spring-security-itest-ldap-embedded-mode-apacheds.gradle @@ -0,0 +1,13 @@ +apply plugin: 'io.spring.convention.spring-test' + +dependencies { + compile project(':spring-security-core') + compile 'org.springframework:spring-beans' + compile 'org.springframework:spring-context' + compile 'org.springframework:spring-core' + compile 'org.springframework:spring-tx' + compile project(':spring-security-config') + compile project(':spring-security-ldap') + + runtime apachedsDependencies +} diff --git a/itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java b/itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java new file mode 100644 index 0000000000..3898aea503 --- /dev/null +++ b/itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.security.config.BeanIds; +import org.springframework.security.ldap.server.ApacheDSContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Eddú Meléndez + */ +public class LdapServerBeanDefinitionParserTests { + + private ClassPathXmlApplicationContext context; + + @Before + public void setup() { + this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml"); + } + + @After + public void closeAppContext() { + if (this.context != null) { + this.context.close(); + this.context = null; + } + } + + @Test + public void apacheDirectoryServerIsStartedByDefault() { + String[] beanNames = this.context.getBeanNamesForType(ApacheDSContainer.class); + assertThat(beanNames).hasSize(1); + assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_APACHE_DS); + } + +} diff --git a/itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/applicationContext-security.xml b/itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/applicationContext-security.xml new file mode 100644 index 0000000000..f980c6ca98 --- /dev/null +++ b/itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/applicationContext-security.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/users.ldif b/itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/users.ldif new file mode 100644 index 0000000000..222e03793c --- /dev/null +++ b/itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/users.ldif @@ -0,0 +1,60 @@ +dn: ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: ou=people,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: people + +dn: uid=rod,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Rod Johnson +sn: Johnson +uid: rod +userPassword: koala + +dn: uid=dianne,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Dianne Emu +sn: Emu +uid: dianne +userPassword: emu + +dn: uid=scott,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Scott +sn: Wombat +uid: scott +userPassword: wombat + +dn: cn=user,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: user +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org +member: uid=scott,ou=people,dc=springframework,dc=org + +dn: cn=teller,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: teller +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org + +dn: cn=supervisor,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: supervisor +member: uid=rod,ou=people,dc=springframework,dc=org diff --git a/itest/ldap/embedded-ldap-mode-unboundid/spring-security-itest-ldap-embedded-mode-unboundid.gradle b/itest/ldap/embedded-ldap-mode-unboundid/spring-security-itest-ldap-embedded-mode-unboundid.gradle new file mode 100644 index 0000000000..45f180468b --- /dev/null +++ b/itest/ldap/embedded-ldap-mode-unboundid/spring-security-itest-ldap-embedded-mode-unboundid.gradle @@ -0,0 +1,13 @@ +apply plugin: 'io.spring.convention.spring-test' + +dependencies { + compile project(':spring-security-core') + compile 'org.springframework:spring-beans' + compile 'org.springframework:spring-context' + compile 'org.springframework:spring-core' + compile 'org.springframework:spring-tx' + compile project(':spring-security-config') + compile project(':spring-security-ldap') + + testCompile "com.unboundid:unboundid-ldapsdk" +} diff --git a/itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java b/itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java new file mode 100644 index 0000000000..e169615b21 --- /dev/null +++ b/itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.security.config.BeanIds; +import org.springframework.security.ldap.server.UnboundIdContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Eddú Meléndez + */ +public class LdapServerBeanDefinitionParserTests { + + private ClassPathXmlApplicationContext context; + + @Before + public void setup() { + this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml"); + } + + @After + public void closeAppContext() { + if (this.context != null) { + this.context.close(); + this.context = null; + } + } + + @Test + public void apacheDirectoryServerIsStartedByDefault() { + String[] beanNames = this.context.getBeanNamesForType(UnboundIdContainer.class); + assertThat(beanNames).hasSize(1); + assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_UNBOUNDID); + } + +} diff --git a/itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/applicationContext-security.xml b/itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/applicationContext-security.xml new file mode 100644 index 0000000000..6254829b43 --- /dev/null +++ b/itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/applicationContext-security.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/users.ldif b/itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/users.ldif new file mode 100644 index 0000000000..222e03793c --- /dev/null +++ b/itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/users.ldif @@ -0,0 +1,60 @@ +dn: ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: ou=people,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: people + +dn: uid=rod,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Rod Johnson +sn: Johnson +uid: rod +userPassword: koala + +dn: uid=dianne,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Dianne Emu +sn: Emu +uid: dianne +userPassword: emu + +dn: uid=scott,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Scott +sn: Wombat +uid: scott +userPassword: wombat + +dn: cn=user,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: user +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org +member: uid=scott,ou=people,dc=springframework,dc=org + +dn: cn=teller,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: teller +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org + +dn: cn=supervisor,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: supervisor +member: uid=rod,ou=people,dc=springframework,dc=org diff --git a/itest/ldap/embedded-ldap-none/spring-security-itest-ldap-embedded-none.gradle b/itest/ldap/embedded-ldap-none/spring-security-itest-ldap-embedded-none.gradle new file mode 100644 index 0000000000..79d8418fde --- /dev/null +++ b/itest/ldap/embedded-ldap-none/spring-security-itest-ldap-embedded-none.gradle @@ -0,0 +1,11 @@ +apply plugin: 'io.spring.convention.spring-test' + +dependencies { + compile project(':spring-security-core') + compile 'org.springframework:spring-beans' + compile 'org.springframework:spring-context' + compile 'org.springframework:spring-core' + compile 'org.springframework:spring-tx' + compile project(':spring-security-config') + compile project(':spring-security-ldap') +} diff --git a/itest/ldap/embedded-ldap-none/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java b/itest/ldap/embedded-ldap-none/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java new file mode 100644 index 0000000000..ce6677bd68 --- /dev/null +++ b/itest/ldap/embedded-ldap-none/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security; + +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.springframework.beans.factory.BeanDefinitionStoreException; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author Eddú Meléndez + */ +public class LdapServerBeanDefinitionParserTests { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private ClassPathXmlApplicationContext context; + + @After + public void closeAppContext() { + if (this.context != null) { + this.context.close(); + this.context = null; + } + } + + @Test + public void apacheDirectoryServerIsStartedByDefault() { + this.thrown.expect(BeanDefinitionStoreException.class); + this.thrown.expectMessage("Embedded LDAP server is not provided"); + + this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml"); + } + +} diff --git a/itest/ldap/embedded-ldap-none/src/integration-test/resources/applicationContext-security.xml b/itest/ldap/embedded-ldap-none/src/integration-test/resources/applicationContext-security.xml new file mode 100644 index 0000000000..da547d0b04 --- /dev/null +++ b/itest/ldap/embedded-ldap-none/src/integration-test/resources/applicationContext-security.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/itest/ldap/embedded-ldap-none/src/integration-test/resources/users.ldif b/itest/ldap/embedded-ldap-none/src/integration-test/resources/users.ldif new file mode 100644 index 0000000000..222e03793c --- /dev/null +++ b/itest/ldap/embedded-ldap-none/src/integration-test/resources/users.ldif @@ -0,0 +1,60 @@ +dn: ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: ou=people,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: people + +dn: uid=rod,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Rod Johnson +sn: Johnson +uid: rod +userPassword: koala + +dn: uid=dianne,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Dianne Emu +sn: Emu +uid: dianne +userPassword: emu + +dn: uid=scott,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Scott +sn: Wombat +uid: scott +userPassword: wombat + +dn: cn=user,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: user +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org +member: uid=scott,ou=people,dc=springframework,dc=org + +dn: cn=teller,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: teller +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org + +dn: cn=supervisor,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: supervisor +member: uid=rod,ou=people,dc=springframework,dc=org diff --git a/itest/ldap/embedded-ldap-unboundid-default/spring-security-itest-ldap-embedded-unboundid-default.gradle b/itest/ldap/embedded-ldap-unboundid-default/spring-security-itest-ldap-embedded-unboundid-default.gradle new file mode 100644 index 0000000000..45f180468b --- /dev/null +++ b/itest/ldap/embedded-ldap-unboundid-default/spring-security-itest-ldap-embedded-unboundid-default.gradle @@ -0,0 +1,13 @@ +apply plugin: 'io.spring.convention.spring-test' + +dependencies { + compile project(':spring-security-core') + compile 'org.springframework:spring-beans' + compile 'org.springframework:spring-context' + compile 'org.springframework:spring-core' + compile 'org.springframework:spring-tx' + compile project(':spring-security-config') + compile project(':spring-security-ldap') + + testCompile "com.unboundid:unboundid-ldapsdk" +} diff --git a/itest/ldap/embedded-ldap-unboundid-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java b/itest/ldap/embedded-ldap-unboundid-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java new file mode 100644 index 0000000000..e169615b21 --- /dev/null +++ b/itest/ldap/embedded-ldap-unboundid-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.security.config.BeanIds; +import org.springframework.security.ldap.server.UnboundIdContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Eddú Meléndez + */ +public class LdapServerBeanDefinitionParserTests { + + private ClassPathXmlApplicationContext context; + + @Before + public void setup() { + this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml"); + } + + @After + public void closeAppContext() { + if (this.context != null) { + this.context.close(); + this.context = null; + } + } + + @Test + public void apacheDirectoryServerIsStartedByDefault() { + String[] beanNames = this.context.getBeanNamesForType(UnboundIdContainer.class); + assertThat(beanNames).hasSize(1); + assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_UNBOUNDID); + } + +} diff --git a/itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/applicationContext-security.xml b/itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/applicationContext-security.xml new file mode 100644 index 0000000000..da547d0b04 --- /dev/null +++ b/itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/applicationContext-security.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/users.ldif b/itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/users.ldif new file mode 100644 index 0000000000..222e03793c --- /dev/null +++ b/itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/users.ldif @@ -0,0 +1,60 @@ +dn: ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: ou=people,dc=springframework,dc=org +objectclass: top +objectclass: organizationalUnit +ou: people + +dn: uid=rod,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Rod Johnson +sn: Johnson +uid: rod +userPassword: koala + +dn: uid=dianne,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Dianne Emu +sn: Emu +uid: dianne +userPassword: emu + +dn: uid=scott,ou=people,dc=springframework,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +cn: Scott +sn: Wombat +uid: scott +userPassword: wombat + +dn: cn=user,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: user +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org +member: uid=scott,ou=people,dc=springframework,dc=org + +dn: cn=teller,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: teller +member: uid=rod,ou=people,dc=springframework,dc=org +member: uid=dianne,ou=people,dc=springframework,dc=org + +dn: cn=supervisor,ou=groups,dc=springframework,dc=org +objectclass: top +objectclass: groupOfNames +cn: supervisor +member: uid=rod,ou=people,dc=springframework,dc=org