diff --git a/config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.groovy b/config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.groovy deleted file mode 100644 index d31fc46d1c..0000000000 --- a/config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.groovy +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2002-2013 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.annotation.authentication.ldap - -import org.springframework.beans.factory.config.AutowireCapableBeanFactory -import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Import -import org.springframework.ldap.core.ContextSource; -import org.springframework.ldap.core.support.BaseLdapPathContextSource; -import org.springframework.security.authentication.AuthenticationManager -import org.springframework.security.authentication.AuthenticationProvider -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.config.annotation.BaseSpringSpec -import org.springframework.security.config.annotation.SecurityBuilder; -import org.springframework.security.config.annotation.authentication.AuthenticationManagerBuilder -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder -import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication -import org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor -import org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessorTests -import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder -import org.springframework.security.ldap.DefaultSpringSecurityContextSource; -import org.springframework.security.ldap.authentication.LdapAuthenticationProvider; -import org.springframework.security.ldap.server.ApacheDSContainer; -import org.springframework.test.util.ReflectionTestUtils; - -/** - * - * @author Rob Winch - * - */ -class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSpec { - def "default configuration"() { - when: - loadConfig(DefaultLdapConfig) - LdapAuthenticationProvider provider = ldapProvider() - then: - provider.authoritiesPopulator.groupRoleAttribute == "cn" - provider.authoritiesPopulator.groupSearchBase == "" - provider.authoritiesPopulator.groupSearchFilter == "(uniqueMember={0})" - ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "ROLE_" - - } - - @Configuration - static class DefaultLdapConfig extends BaseLdapProviderConfig { - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .ldapAuthentication() - .contextSource(contextSource()) - .userDnPatterns("uid={0},ou=people") - } - } - - def "group roles custom"() { - when: - loadConfig(GroupRolesConfig) - LdapAuthenticationProvider provider = ldapProvider() - then: - provider.authoritiesPopulator.groupRoleAttribute == "group" - } - - @Configuration - static class GroupRolesConfig extends BaseLdapProviderConfig { - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .ldapAuthentication() - .contextSource(contextSource()) - .userDnPatterns("uid={0},ou=people") - .groupRoleAttribute("group") - } - } - - def "group search custom"() { - when: - loadConfig(GroupSearchConfig) - LdapAuthenticationProvider provider = ldapProvider() - then: - provider.authoritiesPopulator.groupSearchFilter == "ou=groupName" - } - - @Configuration - static class GroupSearchConfig extends BaseLdapProviderConfig { - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .ldapAuthentication() - .contextSource(contextSource()) - .userDnPatterns("uid={0},ou=people") - .groupSearchFilter("ou=groupName"); - } - } - - def "role prefix custom"() { - when: - loadConfig(RolePrefixConfig) - LdapAuthenticationProvider provider = ldapProvider() - then: - ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "role_" - } - - @Configuration - static class RolePrefixConfig extends BaseLdapProviderConfig { - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .ldapAuthentication() - .contextSource(contextSource()) - .userDnPatterns("uid={0},ou=people") - .rolePrefix("role_") - } - } - - def "bind authentication"() { - when: - loadConfig(BindAuthenticationConfig) - AuthenticationManager auth = context.getBean(AuthenticationManager) - then: - auth - auth.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"] - } - - @Configuration - static class BindAuthenticationConfig extends BaseLdapServerConfig { - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .ldapAuthentication() - .contextSource(contextSource()) - .groupSearchBase("ou=groups") - .groupSearchFilter("(member={0})") - .userDnPatterns("uid={0},ou=people"); - } - } - - def "SEC-2472: Can use crypto PasswordEncoder"() { - setup: - loadConfig(PasswordEncoderConfig) - when: - AuthenticationManager auth = context.getBean(AuthenticationManager) - then: - auth.authenticate(new UsernamePasswordAuthenticationToken("bcrypt","password")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"] - } - - @Configuration - static class PasswordEncoderConfig extends BaseLdapServerConfig { - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .ldapAuthentication() - .contextSource(contextSource()) - .passwordEncoder(new BCryptPasswordEncoder()) - .groupSearchBase("ou=groups") - .groupSearchFilter("(member={0})") - .userDnPatterns("uid={0},ou=people"); - } - } - - def ldapProvider() { - context.getBean(AuthenticationManager).providers[0] - } - - @Configuration - static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig { - @Bean - public ApacheDSContainer ldapServer() throws Exception { - ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif"); - apacheDSContainer.setPort(getPort()); - return apacheDSContainer; - } - } - - @Configuration - @EnableGlobalAuthentication - @Import(ObjectPostProcessorConfiguration) - static abstract class BaseLdapProviderConfig { - - @Bean - public BaseLdapPathContextSource contextSource() throws Exception { - DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource( - "ldap://127.0.0.1:"+ getPort() + "/dc=springframework,dc=org") - contextSource.userDn = "uid=admin,ou=system" - contextSource.password = "secret" - contextSource.afterPropertiesSet() - return contextSource; - } - - @Bean - public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) { - configure(auth) - auth.build() - } - - abstract protected void configure(AuthenticationManagerBuilder auth) throws Exception - } - - static Integer port; - - static int getPort() { - if(port == null) { - ServerSocket socket = new ServerSocket(0) - port = socket.localPort - socket.close() - } - port - } -} diff --git a/config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.groovy b/config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.groovy deleted file mode 100644 index 21382b42c6..0000000000 --- a/config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.groovy +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2002-2016 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.annotation.authentication.ldap - -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.config.annotation.BaseSpringSpec -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter -import org.springframework.security.core.authority.SimpleGrantedAuthority - -/** - * - * @author Rob Winch - * @author EddĂș MelĂ©ndez - * - */ -class LdapAuthenticationProviderConfigurerTests extends BaseSpringSpec { - - def "authentication-manager support multiple default ldap contexts (ports dynamically allocated)"() { - when: - loadConfig(MultiLdapAuthenticationProvidersConfig) - then: - authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")) - } - - def "authentication-manager support multiple ldap context with default role prefix" () { - when: - loadConfig(MultiLdapAuthenticationProvidersConfig) - then: - def authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob", "bobspassword")) - authenticate.authorities.contains(new SimpleGrantedAuthority("ROLE_DEVELOPERS")) - } - - def "authentication-manager support multiple ldap context with custom role prefix"() { - when: - loadConfig(MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig) - then: - def authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob", "bobspassword")) - authenticate.authorities.contains(new SimpleGrantedAuthority("ROL_DEVELOPERS")) - } - - @EnableWebSecurity - static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .ldapAuthentication() - .groupSearchBase("ou=groups") - .groupSearchFilter("(member={0})") - .userDnPatterns("uid={0},ou=people") - .and() - .ldapAuthentication() - .groupSearchBase("ou=groups") - .groupSearchFilter("(member={0})") - .userDnPatterns("uid={0},ou=people") - } - } - - @EnableWebSecurity - static class MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig extends - WebSecurityConfigurerAdapter { - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .ldapAuthentication() - .groupSearchBase("ou=groups") - .groupSearchFilter("(member={0})") - .userDnPatterns("uid={0},ou=people") - .rolePrefix("ROL_") - .and() - .ldapAuthentication() - .groupSearchBase("ou=groups") - .groupSearchFilter("(member={0})") - .userDnPatterns("uid={0},ou=people") - .rolePrefix("RUOLO_") - } - } -} diff --git a/config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.groovy b/config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.groovy deleted file mode 100644 index 9558f4877a..0000000000 --- a/config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.groovy +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2002-2013 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.annotation.authentication.ldap - -import static org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.* - -import org.springframework.ldap.core.support.BaseLdapPathContextSource -import org.springframework.security.authentication.AuthenticationManager -import org.springframework.security.authentication.AuthenticationProvider -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.config.annotation.BaseSpringSpec -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.LdapAuthenticationProviderConfig; -import org.springframework.security.ldap.authentication.LdapAuthenticationProvider; -import org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator; -import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator; -import org.springframework.security.ldap.userdetails.PersonContextMapper; -import org.springframework.test.util.ReflectionTestUtils; - -/** - * - * @author Rob Winch - * - */ -class NamespaceLdapAuthenticationProviderTests extends BaseSpringSpec { - def "ldap-authentication-provider"() { - when: - loadConfig(LdapAuthenticationProviderConfig) - then: - authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")) - } - - def "ldap-authentication-provider custom"() { - when: - loadConfig(CustomLdapAuthenticationProviderConfig) - LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider) - then: - provider.authoritiesPopulator.groupRoleAttribute == "cn" - provider.authoritiesPopulator.groupSearchBase == "ou=groups" - provider.authoritiesPopulator.groupSearchFilter == "(member={0})" - ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "PREFIX_" - provider.userDetailsContextMapper instanceof PersonContextMapper - provider.authenticator.getUserDns("user") == ["uid=user,ou=people"] - provider.authenticator.userSearch.searchBase == "ou=users" - provider.authenticator.userSearch.searchFilter == "(uid={0})" - } - - def "SEC-2490: ldap-authentication-provider custom LdapAuthoritiesPopulator"() { - setup: - LdapAuthoritiesPopulator LAP = Mock() - CustomAuthoritiesPopulatorConfig.LAP = LAP - when: - loadConfig(CustomAuthoritiesPopulatorConfig) - LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider) - then: - provider.authoritiesPopulator == LAP - } - - def "ldap-authentication-provider password compare"() { - when: - loadConfig(PasswordCompareLdapConfig) - LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider) - then: - provider.authenticator instanceof PasswordComparisonAuthenticator - authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")) - } -} diff --git a/config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy b/config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy deleted file mode 100644 index 4bfc77ca2a..0000000000 --- a/config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy +++ /dev/null @@ -1,164 +0,0 @@ -package org.springframework.security.config.ldap - -import org.springframework.security.crypto.password.NoOpPasswordEncoder - -import static org.mockito.Mockito.* - -import java.text.MessageFormat - -import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder -import org.springframework.security.config.AbstractXmlConfigTests -import org.springframework.security.config.BeanIds -import org.springframework.security.util.FieldUtils -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.context.ApplicationContextException -import org.springframework.security.core.AuthenticationException -import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper - -/** - * @author Luke Taylor - */ -class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests { - - // SEC-1182 - def multipleProvidersAreSupported() { - xml.'ldap-server'(url: 'ldap://blah:389/dc=blah') - xml.'authentication-manager'() { - 'ldap-authentication-provider'('group-search-filter': 'member={0}') - 'ldap-authentication-provider'('group-search-filter': 'uniqueMember={0}') - } - - createAppContext('') - - def providers = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers - - expect: - - providers.size() == 2 - providers[0].authoritiesPopulator.groupSearchFilter == "member={0}" - providers[1].authoritiesPopulator.groupSearchFilter == "uniqueMember={0}" - } - - - def simpleProviderAuthenticatesCorrectly() { - xml.'ldap-server'(ldif:'test-server.ldif') - xml.'authentication-manager'{ - 'ldap-authentication-provider'('group-search-filter':'member={0}') - } - - createAppContext('') - - def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) - - when: - def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")) - def ben = auth.principal; - - then: - ben.authorities.size() == 3 - } - - def missingServerEltCausesConfigException() { - xml.'authentication-manager'{ - 'ldap-authentication-provider'() - } - - when: - createAppContext('') - - then: - thrown(ApplicationContextException) - } - - def supportsPasswordComparisonAuthentication() { - xml.'ldap-server'(ldif:'test-server.ldif') - xml.'authentication-manager'{ - 'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') - 'password-compare' - } - createAppContext('') - def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) - - when: - def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")) - - then: - auth != null - notThrown(AuthenticationException) - } - - def supportsPasswordComparisonAuthenticationWithPasswordEncoder() { - xml.'ldap-server'(ldif:'test-server.ldif') - xml.'authentication-manager'{ - 'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') { - 'password-compare'('password-attribute': 'uid') { - 'password-encoder'(ref: 'passwordEncoder') - } - } - } - xml.'b:bean'(id: 'passwordEncoder', 'class' : NoOpPasswordEncoder.name, 'factory-method': 'getInstance') - - createAppContext('') - def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) - - when: - def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben")) - - then: - auth != null - notThrown(AuthenticationException) - } - - def 'SEC-2472: Supports Crypto PasswordEncoder'() { - setup: - xml.'ldap-server'(ldif:'test-server.ldif') - xml.'authentication-manager'{ - 'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') { - 'password-compare'() { - 'password-encoder'(ref: 'pe') - } - } - } - xml.'b:bean'(id:'pe','class':BCryptPasswordEncoder.class.name) - - createAppContext('') - def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) - - when: - def auth = am.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", 'password')) - - then: - auth != null - } - - def inetOrgContextMapperIsSupported() { - xml.'ldap-server'(url: 'ldap://127.0.0.1:343/dc=springframework,dc=org') - xml.'authentication-manager'{ - 'ldap-authentication-provider'('user-details-class' :'inetOrgPerson') - } - createAppContext('') - - expect: - appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0].userDetailsContextMapper instanceof InetOrgPersonContextMapper - } - - def ldapAuthenticationProviderWorksWithPlaceholders() { - System.setProperty('udp','people') - System.setProperty('gsf','member') - - xml.'ldap-server'() - xml.'authentication-manager'{ - 'ldap-authentication-provider'('user-dn-pattern':'uid={0},ou=${udp}','group-search-filter':'${gsf}={0}') - } - bean(PropertyPlaceholderConfigurer.class.name, PropertyPlaceholderConfigurer.class) - - createAppContext('') - def provider = this.appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0] - - expect: - [new MessageFormat("uid={0},ou=people")] == FieldUtils.getFieldValue(provider,"authenticator.userDnFormat") - "member={0}" == FieldUtils.getFieldValue(provider, "authoritiesPopulator.groupSearchFilter") - } -} diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java new file mode 100644 index 0000000000..34a4be0934 --- /dev/null +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java @@ -0,0 +1,250 @@ +/* + * 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.annotation.authentication.ldap; + +import org.junit.Rule; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.ldap.core.support.BaseLdapPathContextSource; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication; +import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.test.SpringTestRule; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.ldap.DefaultSpringSecurityContextSource; +import org.springframework.security.ldap.authentication.LdapAuthenticationProvider; +import org.springframework.security.ldap.server.ApacheDSContainer; +import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; + +import java.io.IOException; +import java.net.ServerSocket; +import java.util.List; + +import static java.util.Collections.singleton; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; +import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; + +public class LdapAuthenticationProviderBuilderSecurityBuilderTests { + @Rule + public final SpringTestRule spring = new SpringTestRule(); + + @Autowired + private MockMvc mockMvc; + + @Autowired + private AuthenticationManager authenticationManager; + + @Test + public void defaultConfiguration() { + this.spring.register(DefaultLdapConfig.class).autowire(); + LdapAuthenticationProvider provider = ldapProvider(); + + LdapAuthoritiesPopulator authoritiesPopulator = getAuthoritiesPopulator(provider); + assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupRoleAttribute", "cn"); + assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchBase", ""); + assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchFilter", "(uniqueMember={0})"); + assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("ROLE_"); + } + + @EnableWebSecurity + static class DefaultLdapConfig extends BaseLdapProviderConfig { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .contextSource(contextSource()) + .userDnPatterns("uid={0},ou=people"); + } + // @formatter:on + } + + @Test + public void groupRolesCustom() { + this.spring.register(GroupRolesConfig.class).autowire(); + LdapAuthenticationProvider provider = ldapProvider(); + + assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupRoleAttribute")).isEqualTo("group"); + } + + @EnableWebSecurity + static class GroupRolesConfig extends BaseLdapProviderConfig { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .contextSource(contextSource()) + .userDnPatterns("uid={0},ou=people") + .groupRoleAttribute("group"); + } + // @formatter:on + } + + @Test + public void groupSearchCustom() { + this.spring.register(GroupSearchConfig.class).autowire(); + LdapAuthenticationProvider provider = ldapProvider(); + + assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupSearchFilter")).isEqualTo("ou=groupName"); + } + + @EnableWebSecurity + static class GroupSearchConfig extends BaseLdapProviderConfig { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .contextSource(contextSource()) + .userDnPatterns("uid={0},ou=people") + .groupSearchFilter("ou=groupName"); + } + // @formatter:on + } + + @Test + public void rolePrefixCustom() { + this.spring.register(RolePrefixConfig.class).autowire(); + LdapAuthenticationProvider provider = ldapProvider(); + + assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("role_"); + } + + @EnableWebSecurity + static class RolePrefixConfig extends BaseLdapProviderConfig { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .contextSource(contextSource()) + .userDnPatterns("uid={0},ou=people") + .rolePrefix("role_"); + } + // @formatter:on + } + + @Test + public void bindAuthentication() throws Exception { + this.spring.register(BindAuthenticationConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) + .andExpect(authenticated().withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); + } + + @EnableWebSecurity + static class BindAuthenticationConfig extends BaseLdapServerConfig { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .contextSource(contextSource()) + .groupSearchBase("ou=groups") + .groupSearchFilter("(member={0})") + .userDnPatterns("uid={0},ou=people"); + } + // @formatter:on + } + + // SEC-2472 + @Test + public void canUseCryptoPasswordEncoder() throws Exception { + this.spring.register(PasswordEncoderConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bcrypt").password("password")) + .andExpect(authenticated().withUsername("bcrypt").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); + } + + @EnableWebSecurity + static class PasswordEncoderConfig extends BaseLdapServerConfig { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .contextSource(contextSource()) + .passwordEncoder(new BCryptPasswordEncoder()) + .groupSearchBase("ou=groups") + .groupSearchFilter("(member={0})") + .userDnPatterns("uid={0},ou=people"); + } + // @formatter:on + } + + private LdapAuthenticationProvider ldapProvider() { + return ((List) ReflectionTestUtils.getField(authenticationManager, "providers")).get(0); + } + + private LdapAuthoritiesPopulator getAuthoritiesPopulator(LdapAuthenticationProvider provider) { + return (LdapAuthoritiesPopulator) ReflectionTestUtils.getField(provider, "authoritiesPopulator"); + } + + private GrantedAuthoritiesMapper getAuthoritiesMapper(LdapAuthenticationProvider provider) { + return (GrantedAuthoritiesMapper) ReflectionTestUtils.getField(provider, "authoritiesMapper"); + } + + @EnableWebSecurity + static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig { + @Bean + public ApacheDSContainer ldapServer() throws Exception { + ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif"); + apacheDSContainer.setPort(getPort()); + return apacheDSContainer; + } + } + + @EnableWebSecurity + @EnableGlobalAuthentication + @Import(ObjectPostProcessorConfiguration.class) + static abstract class BaseLdapProviderConfig extends WebSecurityConfigurerAdapter { + + @Bean + public BaseLdapPathContextSource contextSource() throws Exception { + DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource( + "ldap://127.0.0.1:" + getPort() + "/dc=springframework,dc=org"); + contextSource.setUserDn("uid=admin,ou=system"); + contextSource.setPassword("secret"); + contextSource.afterPropertiesSet(); + return contextSource; + } + + @Bean + public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) throws Exception { + configure(auth); + return auth.build(); + } + + abstract protected void configure(AuthenticationManagerBuilder auth) throws Exception; + } + + static Integer port; + + static int getPort() throws IOException { + if (port == null) { + ServerSocket socket = new ServerSocket(0); + port = socket.getLocalPort(); + socket.close(); + } + return port; + } +} diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java new file mode 100644 index 0000000000..a2cdc44e88 --- /dev/null +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java @@ -0,0 +1,101 @@ +/* + * 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.annotation.authentication.ldap; + +import org.junit.Rule; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.test.SpringTestRule; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.test.web.servlet.MockMvc; + +import static java.util.Collections.singleton; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; +import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; + +public class LdapAuthenticationProviderConfigurerTests { + @Rule + public final SpringTestRule spring = new SpringTestRule(); + + @Autowired + private MockMvc mockMvc; + + @Test + public void authenticationManagerSupportMultipleDefaultLdapContextsWithPortsDynamicallyAllocated() throws Exception { + this.spring.register(MultiLdapAuthenticationProvidersConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) + .andExpect(authenticated().withUsername("bob")); + } + + @Test + public void authenticationManagerSupportMultipleLdapContextWithDefaultRolePrefix() throws Exception { + this.spring.register(MultiLdapAuthenticationProvidersConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) + .andExpect(authenticated().withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); + } + + @Test + public void authenticationManagerSupportMultipleLdapContextWithCustomRolePrefix() throws Exception { + this.spring.register(MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) + .andExpect(authenticated().withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROL_DEVELOPERS")))); + } + + @EnableWebSecurity + static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .groupSearchBase("ou=groups") + .groupSearchFilter("(member={0})") + .userDnPatterns("uid={0},ou=people") + .and() + .ldapAuthentication() + .groupSearchBase("ou=groups") + .groupSearchFilter("(member={0})") + .userDnPatterns("uid={0},ou=people"); + } + // @formatter:on + } + + @EnableWebSecurity + static class MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .groupSearchBase("ou=groups") + .groupSearchFilter("(member={0})") + .userDnPatterns("uid={0},ou=people") + .rolePrefix("ROL_") + .and() + .ldapAuthentication() + .groupSearchBase("ou=groups") + .groupSearchFilter("(member={0})") + .userDnPatterns("uid={0},ou=people") + .rolePrefix("RUOLO_"); + } + // @formatter:on + } +} diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.java new file mode 100644 index 0000000000..527d0f0462 --- /dev/null +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.java @@ -0,0 +1,95 @@ +/* + * 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.annotation.authentication.ldap; + +import org.junit.Rule; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.support.LdapContextSource; +import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.CustomAuthoritiesPopulatorConfig; +import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.CustomLdapAuthenticationProviderConfig; +import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.LdapAuthenticationProviderConfig; +import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.PasswordCompareLdapConfig; +import org.springframework.security.config.test.SpringTestRule; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.ldap.DefaultSpringSecurityContextSource; +import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator; +import org.springframework.security.web.FilterChainProxy; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; +import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; + +public class NamespaceLdapAuthenticationProviderTests { + + @Rule + public final SpringTestRule spring = new SpringTestRule(); + + @Autowired + private MockMvc mockMvc; + + @Autowired + private FilterChainProxy filterChainProxy; + + @Test + public void ldapAuthenticationProvider() throws Exception { + this.spring.register(LdapAuthenticationProviderConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) + .andExpect(authenticated().withUsername("bob")); + } + + @Test + public void ldapAuthenticationProviderCustom() throws Exception { + this.spring.register(CustomLdapAuthenticationProviderConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) + .andExpect(authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("PREFIX_DEVELOPERS")))); + } + + // SEC-2490 + @Test + public void ldapAuthenticationProviderCustomLdapAuthoritiesPopulator() throws Exception { + LdapContextSource contextSource = new DefaultSpringSecurityContextSource("ldap://blah.example.com:789/dc=springframework,dc=org"); + CustomAuthoritiesPopulatorConfig.LAP = new DefaultLdapAuthoritiesPopulator(contextSource, null) { + @Override + protected Set getAdditionalRoles(DirContextOperations user, String username) { + return new HashSet<>(AuthorityUtils.createAuthorityList("ROLE_EXTRA")); + } + }; + + this.spring.register(CustomAuthoritiesPopulatorConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) + .andExpect(authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA")))); + } + + @Test + public void ldapAuthenticationProviderPasswordCompare() throws Exception { + this.spring.register(PasswordCompareLdapConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bcrypt").password("password")) + .andExpect(authenticated().withUsername("bcrypt")); + } +} diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java index 4d0aad3d99..c349ce6a1b 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java @@ -18,7 +18,7 @@ package org.springframework.security.config.annotation.authentication.ldap; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator; import org.springframework.security.ldap.userdetails.PersonContextMapper; @@ -90,7 +90,7 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs { .groupSearchBase("ou=groups") .userSearchFilter("(uid={0})") .passwordCompare() - .passwordEncoder(NoOpPasswordEncoder.getInstance()) // ldap-authentication-provider/password-compare/password-encoder@ref + .passwordEncoder(new BCryptPasswordEncoder()) // ldap-authentication-provider/password-compare/password-encoder@ref .passwordAttribute("userPassword"); // ldap-authentication-provider/password-compare@password-attribute } // @formatter:on diff --git a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.java b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.java new file mode 100644 index 0000000000..eefa4e2f77 --- /dev/null +++ b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.java @@ -0,0 +1,177 @@ +/* + * 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.context.ApplicationContextException; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.config.BeanIds; +import org.springframework.security.config.util.InMemoryXmlApplicationContext; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper; + +import java.text.MessageFormat; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LdapProviderBeanDefinitionParserTests { + InMemoryXmlApplicationContext appCtx; + + @After + public void closeAppContext() { + if (appCtx != null) { + appCtx.close(); + appCtx = null; + } + } + + @Test + public void simpleProviderAuthenticatesCorrectly() { + appCtx = new InMemoryXmlApplicationContext("" + + "" + + " " + + "" + ); + + AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class); + Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")); + UserDetails ben = (UserDetails) auth.getPrincipal(); + assertThat(ben.getAuthorities()).hasSize(3); + } + + @Test + public void multipleProvidersAreSupported() { + appCtx = new InMemoryXmlApplicationContext("" + + "" + + " " + + " " + + "" + ); + + ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class); + assertThat(providerManager.getProviders()).hasSize(2); + assertThat(providerManager.getProviders()) + .extracting("authoritiesPopulator.groupSearchFilter") + .containsExactly("member={0}", "uniqueMember={0}"); + } + + @Test(expected = ApplicationContextException.class) + public void missingServerEltCausesConfigException() { + new InMemoryXmlApplicationContext("" + + " " + + "" + ); + } + + @Test + public void supportsPasswordComparisonAuthentication() { + appCtx = new InMemoryXmlApplicationContext("" + + "" + + " " + + " " + + " " + + "" + ); + + AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class); + Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")); + + assertThat(auth).isNotNull(); + } + + @Test + public void supportsPasswordComparisonAuthenticationWithPasswordEncoder() { + appCtx = new InMemoryXmlApplicationContext("" + + "" + + " " + + " " + + " " + + " " + + " " + + "" + + "" + ); + + AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class); + Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben")); + + assertThat(auth).isNotNull(); + } + + // SEC-2472 + @Test + public void supportsCryptoPasswordEncoder() { + appCtx = new InMemoryXmlApplicationContext("" + + "" + + " " + + " " + + " " + + " " + + " " + + "" + + "" + ); + + AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class); + Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", "password")); + + assertThat(auth).isNotNull(); + } + + @Test + public void inetOrgContextMapperIsSupported() { + appCtx = new InMemoryXmlApplicationContext("" + + "" + + " " + + "" + ); + + ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class); + assertThat(providerManager.getProviders()).hasSize(1); + assertThat(providerManager.getProviders()) + .extracting("userDetailsContextMapper") + .allSatisfy(contextMapper -> assertThat(contextMapper).isInstanceOf(InetOrgPersonContextMapper.class)); + } + + @Test + public void ldapAuthenticationProviderWorksWithPlaceholders() { + System.setProperty("udp", "people"); + System.setProperty("gsf", "member"); + appCtx = new InMemoryXmlApplicationContext("" + + "" + + " " + + "" + + "" + ); + + ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class); + assertThat(providerManager.getProviders()).hasSize(1); + + AuthenticationProvider authenticationProvider = providerManager.getProviders().get(0); + assertThat(authenticationProvider) + .extracting("authenticator.userDnFormat") + .satisfies(messageFormats -> assertThat(messageFormats).isEqualTo(new MessageFormat[]{new MessageFormat("uid={0},ou=people")})); + assertThat(authenticationProvider) + .extracting("authoritiesPopulator.groupSearchFilter") + .satisfies(searchFilter -> assertThat(searchFilter).isEqualTo("member={0}")); + } +} diff --git a/config/src/test/groovy/org/springframework/security/config/AbstractXmlConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/AbstractXmlConfigTests.groovy deleted file mode 100644 index 4bc4f59ffa..0000000000 --- a/config/src/test/groovy/org/springframework/security/config/AbstractXmlConfigTests.groovy +++ /dev/null @@ -1,106 +0,0 @@ -package org.springframework.security.config - -import groovy.xml.MarkupBuilder -import org.mockito.Mockito -import org.springframework.context.ApplicationListener -import org.springframework.context.support.AbstractRefreshableApplicationContext -import org.springframework.mock.web.MockServletContext -import org.springframework.security.CollectingAppListener -import org.springframework.security.config.util.InMemoryXmlApplicationContext -import org.springframework.security.config.util.InMemoryXmlWebApplicationContext -import org.springframework.security.core.context.SecurityContextHolder -import spock.lang.Specification - -import javax.servlet.ServletContext - -import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML -/** - * - * @author Luke Taylor - */ -abstract class AbstractXmlConfigTests extends Specification { - AbstractRefreshableApplicationContext appContext; - Writer writer; - MarkupBuilder xml; - ApplicationListener appListener; - - def setup() { - writer = new StringWriter() - xml = new MarkupBuilder(writer) - appListener = new CollectingAppListener() - } - - def cleanup() { - if (appContext != null) { - appContext.close(); - appContext = null; - } - SecurityContextHolder.clearContext(); - } - - def mockBean(Class clazz, String id = clazz.simpleName) { - xml.'b:bean'(id: id, 'class': Mockito.class.name, 'factory-method':'mock') { - 'b:constructor-arg'(value : clazz.name) - 'b:constructor-arg'(value : id) - } - } - - def bean(String name, Class clazz) { - xml.'b:bean'(id: name, 'class': clazz.name) - } - - def bean(String name, String clazz) { - xml.'b:bean'(id: name, 'class': clazz) - } - - def bean(String name, String clazz, List constructorArgs) { - xml.'b:bean'(id: name, 'class': clazz) { - constructorArgs.each { val -> - 'b:constructor-arg'(value: val) - } - } - } - - def bean(String name, String clazz, Map properties, Map refs) { - xml.'b:bean'(id: name, 'class': clazz) { - properties.each {key, val -> - 'b:property'(name: key, value: val) - } - refs.each {key, val -> - 'b:property'(name: key, ref: val) - } - } - } - - def createAppContext() { - createAppContext(AUTH_PROVIDER_XML) - } - - def createAppContext(String extraXml) { - appContext = new InMemoryXmlApplicationContext(writer.toString() + extraXml); - appContext.addApplicationListener(appListener); - } - - def createWebAppContext() { - createWebAppContext(AUTH_PROVIDER_XML); - } - - def createWebAppContext(ServletContext servletContext) { - createWebAppContext(AUTH_PROVIDER_XML, servletContext); - } - - def createWebAppContext(String extraXml) { - createWebAppContext(extraXml, null); - } - - def createWebAppContext(String extraXml, ServletContext servletContext) { - appContext = new InMemoryXmlWebApplicationContext(writer.toString() + extraXml); - appContext.addApplicationListener(appListener); - if (servletContext != null) { - appContext.setServletContext(servletContext); - } else { - appContext.setServletContext(new MockServletContext()); - } - appContext.refresh(); - } -} diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/AnyObjectPostProcessor.java b/config/src/test/groovy/org/springframework/security/config/annotation/AnyObjectPostProcessor.java deleted file mode 100644 index a2fbdcbe14..0000000000 --- a/config/src/test/groovy/org/springframework/security/config/annotation/AnyObjectPostProcessor.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2002-2013 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.annotation; - -/** - * Exists for mocking purposes to ensure that the Type information is found. - * - * @author Rob Winch - */ -public interface AnyObjectPostProcessor extends ObjectPostProcessor { - -} diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/BaseSpringSpec.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/BaseSpringSpec.groovy deleted file mode 100644 index aabe790534..0000000000 --- a/config/src/test/groovy/org/springframework/security/config/annotation/BaseSpringSpec.groovy +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2002-2013 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.annotation; - -import javax.servlet.Filter - -import spock.lang.AutoCleanup -import spock.lang.Specification - -import org.springframework.beans.factory.NoSuchBeanDefinitionException -import org.springframework.context.ConfigurableApplicationContext -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.mock.web.MockFilterChain -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.mock.web.MockHttpServletResponse -import org.springframework.mock.web.MockServletContext -import org.springframework.security.authentication.AuthenticationManager -import org.springframework.security.authentication.AuthenticationProvider -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder -import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration -import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration -import org.springframework.security.core.Authentication -import org.springframework.security.core.authority.AuthorityUtils -import org.springframework.security.core.context.SecurityContextHolder -import org.springframework.security.core.context.SecurityContextImpl -import org.springframework.security.web.FilterChainProxy -import org.springframework.security.web.access.intercept.FilterSecurityInterceptor -import org.springframework.security.web.context.HttpRequestResponseHolder -import org.springframework.security.web.context.HttpSessionSecurityContextRepository -import org.springframework.security.web.csrf.CsrfToken -import org.springframework.security.web.csrf.DefaultCsrfToken -import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext - -/** - * - * @author Rob Winch - */ -abstract class BaseSpringSpec extends Specification { - boolean allowCircularReferences = false - @AutoCleanup - ConfigurableApplicationContext context - @AutoCleanup - ConfigurableApplicationContext oppContext - - MockHttpServletRequest request - MockHttpServletResponse response - MockFilterChain chain - CsrfToken csrfToken - AuthenticationManagerBuilder authenticationBldr - - def setup() { - authenticationBldr = createAuthenticationManagerBuilder() - setupWeb(null) - } - - def setupWeb(httpSession = null) { - request = new MockHttpServletRequest(method:"GET") - if(httpSession) { - request.session = httpSession - } - response = new MockHttpServletResponse() - chain = new MockFilterChain() - setupCsrf() - } - - def setupCsrf(csrfTokenValue="BaseSpringSpec_CSRFTOKEN",req=request,resp=response) { - csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf",csrfTokenValue) - new HttpSessionCsrfTokenRepository().saveToken(csrfToken, req, resp) - req.setParameter(csrfToken.parameterName, csrfToken.token) - } - - def cleanup() { - SecurityContextHolder.clearContext() - } - - def loadConfig(Class... configs) { - context = new AnnotationConfigWebApplicationContext() - context.setAllowCircularReferences(allowCircularReferences) - context.register(configs) - context.setServletContext(new MockServletContext()) - context.refresh() - context - } - - def findFilter(Class filter, int index = 0) { - filterChain(index).filters.find { filter.isAssignableFrom(it.class)} - } - - def filterChain(int index=0) { - filterChains()[index] - } - - def filterChains() { - context.getBean(FilterChainProxy).filterChains - } - - Filter getSpringSecurityFilterChain() { - context.getBean("springSecurityFilterChain",Filter.class) - } - - def getResponseHeaders() { - def headers = [:] - response.headerNames.each { name -> - headers.put(name, response.getHeaderValues(name).join(',')) - } - return headers - } - - AuthenticationManager authenticationManager() { - context.getBean(AuthenticationManager) - } - - AuthenticationManager getAuthenticationManager() { - try { - authenticationManager().delegateBuilder.getObject() - } catch(NoSuchBeanDefinitionException e) { - } catch(MissingPropertyException e) {} - findFilter(FilterSecurityInterceptor).authenticationManager - } - - List authenticationProviders() { - List providers = new ArrayList() - AuthenticationManager authenticationManager = getAuthenticationManager() - while(authenticationManager?.providers) { - providers.addAll(authenticationManager.providers) - authenticationManager = authenticationManager.parent - } - providers - } - - AuthenticationProvider findAuthenticationProvider(Class provider) { - authenticationProviders().find { provider.isAssignableFrom(it.class) } - } - - def getCurrentAuthentication() { - new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response)).authentication - } - - def login(String username="user", String role="ROLE_USER") { - login(new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))) - } - - def login(Authentication auth) { - HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository() - HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response) - repo.loadContext(requestResponseHolder) - repo.saveContext(new SecurityContextImpl(authentication:auth), requestResponseHolder.request, requestResponseHolder.response) - } - - def createAuthenticationManagerBuilder() { - oppContext = new AnnotationConfigApplicationContext(ObjectPostProcessorConfiguration, AuthenticationConfiguration) - AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(objectPostProcessor) - auth.inMemoryAuthentication().and() - } - - def getObjectPostProcessor() { - oppContext.getBean(ObjectPostProcessor) - } -} diff --git a/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy deleted file mode 100644 index 4d7905255e..0000000000 --- a/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2002-2012 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.http - -import javax.servlet.Filter -import org.springframework.mock.web.MockFilterChain -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.mock.web.MockHttpServletResponse -import org.springframework.security.config.AbstractXmlConfigTests -import org.springframework.security.config.BeanIds -import org.springframework.security.web.FilterInvocation - -import javax.servlet.http.HttpServletRequest - -/** - * - * @author Rob Winch - * - */ -abstract class AbstractHttpConfigTests extends AbstractXmlConfigTests { - final int AUTO_CONFIG_FILTERS = 15; - - def httpAutoConfig(Closure c) { - xml.http(['auto-config': 'true', 'use-expressions':false], c) - } - - def httpAutoConfig(String matcher, Closure c) { - xml.http(['auto-config': 'true', 'use-expressions':false, 'request-matcher': matcher], c) - } - - def interceptUrl(String path, String authz) { - xml.'intercept-url'(pattern: path, access: authz) - } - - def interceptUrl(String path, String httpMethod, String authz) { - xml.'intercept-url'(pattern: path, method: httpMethod, access: authz) - } - - Filter getFilter(Class type) { - List filters = getFilters("/any"); - - for (f in filters) { - if (f.class.isAssignableFrom(type)) { - return f; - } - } - - return null; - } - - List getFilters(String url) { - springSecurityFilterChain.getFilters(url) - } - - Filter getSpringSecurityFilterChain() { - appContext.getBean(BeanIds.FILTER_CHAIN_PROXY) - } - - FilterInvocation createFilterinvocation(String path, String method) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); - request.setMethod(method); - request.setRequestURI(null); - request.setServletPath(path); - - return new FilterInvocation(request, new MockHttpServletResponse(), new MockFilterChain()); - } - - def basicLogin(HttpServletRequest request, String username="user",String password="password") { - def credentials = username + ":" + password - request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64()) - } -}