Add Flag to enable searching of LDAP groups on subtrees

Closes gh-8939
This commit is contained in:
Roberto Paolillo 2020-04-16 20:29:24 +02:00 committed by Rob Winch
parent 64a5bb053e
commit 2cccf223df
3 changed files with 66 additions and 1 deletions

View File

@ -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();

View File

@ -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
}
}

View File

@ -61,6 +61,7 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
extends SecurityConfigurerAdapter<AuthenticationManager, B> {
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 LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
contextSource, groupSearchBase);
defaultAuthoritiesPopulator.setGroupRoleAttribute(groupRoleAttribute);
defaultAuthoritiesPopulator.setGroupSearchFilter(groupSearchFilter);
defaultAuthoritiesPopulator.setSearchSubtree(groupSearchSubtree);
defaultAuthoritiesPopulator.setRolePrefix(this.rolePrefix);
this.ldapAuthoritiesPopulator = defaultAuthoritiesPopulator;
@ -320,6 +322,19 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
return this;
}
/**
* If set to true, a subtree scope search will be performed for group membership. If false a
* single-level search is used.
*
* @param searchSubtree set to true to enable searching of the entire tree below the
* <tt>groupSearchBase</tt>.
* @return the {@link LdapAuthenticationProviderConfigurer} for further customizations
*/
public LdapAuthenticationProviderConfigurer<B> 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.