From 2cccf223df9e59d6439defed78b3d1b838769ca4 Mon Sep 17 00:00:00 2001 From: Roberto Paolillo Date: Thu, 16 Apr 2020 20:29:24 +0200 Subject: [PATCH] Add Flag to enable searching of LDAP groups on subtrees Closes gh-8939 --- ...onProviderBuilderSecurityBuilderTests.java | 27 ++++++++++++++++++- ...AuthenticationProviderConfigurerTests.java | 25 +++++++++++++++++ .../LdapAuthenticationProviderConfigurer.java | 15 +++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) 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 index 34a4be0934..9ff0675bc2 100644 --- 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 @@ -42,7 +42,7 @@ import org.springframework.test.web.servlet.MockMvc; import java.io.IOException; import java.net.ServerSocket; import java.util.List; - +import javax.naming.directory.SearchControls; 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; @@ -67,6 +67,8 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupRoleAttribute", "cn"); assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchBase", ""); assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchFilter", "(uniqueMember={0})"); + assertThat(authoritiesPopulator).extracting("searchControls").hasFieldOrPropertyWithValue("searchScope", + SearchControls.ONELEVEL_SCOPE); assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("ROLE_"); } @@ -124,6 +126,29 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { // @formatter:on } + @Test + public void groupSubtreeSearchCustom() { + this.spring.register(GroupSubtreeSearchConfig.class).autowire(); + LdapAuthenticationProvider provider = ldapProvider(); + + assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "searchControls")) + .extracting("searchScope").isEqualTo(SearchControls.SUBTREE_SCOPE); + } + + @EnableWebSecurity + static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .contextSource(contextSource()) + .userDnPatterns("uid={0},ou=people") + .groupSearchFilter("ou=groupName") + .groupSearchSubtree(true); + } + // @formatter:on + } + @Test public void rolePrefixCustom() { this.spring.register(RolePrefixConfig.class).autowire(); 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 index a6a39dcffe..3cf29d6338 100644 --- 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 @@ -21,9 +21,11 @@ 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.authentication.ldap.LdapAuthenticationProviderBuilderSecurityBuilderTests.BaseLdapProviderConfig; 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.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.test.web.servlet.MockMvc; @@ -70,6 +72,15 @@ public class LdapAuthenticationProviderConfigurerTests { .andExpect(authenticated().withUsername("bob")); } + @Test + public void authenticationManagerWhenSearchSubtreeThenNestedGroupFound() throws Exception { + this.spring.register(GroupSubtreeSearchConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("ben").password("benspassword")) + .andExpect(authenticated().withUsername("ben").withAuthorities( + AuthorityUtils.createAuthorityList("ROLE_SUBMANAGERS", "ROLE_MANAGERS", "ROLE_DEVELOPERS"))); + } + @EnableWebSecurity static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { // @formatter:off @@ -121,4 +132,18 @@ public class LdapAuthenticationProviderConfigurerTests { .port(0); } } + + @EnableWebSecurity + static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig { + // @formatter:off + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .ldapAuthentication() + .groupSearchBase("ou=groups") + .groupSearchFilter("(member={0})") + .groupSearchSubtree(true) + .userDnPatterns("uid={0},ou=people"); + } + // @formatter:on + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java index a5a45106f9..51338a9bab 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java @@ -61,6 +61,7 @@ public class LdapAuthenticationProviderConfigurer { private String groupRoleAttribute = "cn"; private String groupSearchBase = ""; + private boolean groupSearchSubtree = false; private String groupSearchFilter = "(uniqueMember={0})"; private String rolePrefix = "ROLE_"; private String userSearchBase = ""; // only for search @@ -130,6 +131,7 @@ public class LdapAuthenticationProviderConfigurergroupSearchBase. + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + */ + public LdapAuthenticationProviderConfigurer groupSearchSubtree(boolean groupSearchSubtree) { + this.groupSearchSubtree = groupSearchSubtree; + return this; + } + /** * The LDAP filter to search for groups. Defaults to "(uniqueMember={0})". The * substituted parameter is the DN of the user.