diff --git a/src/main/java/hudson/security/LDAPSecurityRealm.java b/src/main/java/hudson/security/LDAPSecurityRealm.java index 50b48ea..f702232 100644 --- a/src/main/java/hudson/security/LDAPSecurityRealm.java +++ b/src/main/java/hudson/security/LDAPSecurityRealm.java @@ -25,6 +25,7 @@ package hudson.security; import groovy.lang.Binding; +import hudson.DescriptorExtensionList; import hudson.Extension; import static hudson.Util.fixEmpty; import static hudson.Util.fixEmptyAndTrim; @@ -68,6 +69,8 @@ import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import jenkins.model.Jenkins; +import jenkins.security.plugins.ldap.FromGroupSearchLDAPGroupMembershipStrategy; +import jenkins.security.plugins.ldap.LDAPGroupMembershipStrategy; import org.acegisecurity.AcegiSecurityException; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; @@ -287,8 +290,15 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { * {@code LDAPBindSecurityRealm.groovy} * * @since 1.5 + * @deprecated use {@link #groupMembershipStrategy} */ - public final String groupMembershipFilter; + @Deprecated + public transient String groupMembershipFilter; + + /** + * @since 2.0 + */ + public /*effectively final*/ LDAPGroupMembershipStrategy groupMembershipStrategy; /* Other configurations that are needed: @@ -402,8 +412,16 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { this(server, rootDN, userSearchBase, userSearch, groupSearchBase, groupSearchFilter, groupMembershipFilter, managerDN, Secret.fromString(managerPassword), inhibitInferRootDN, disableMailAddressResolver, cache, environmentProperties, null, null); } - @DataBoundConstructor + /** + * @deprecated retained for backwards binary compatibility. + */ + @Deprecated public LDAPSecurityRealm(String server, String rootDN, String userSearchBase, String userSearch, String groupSearchBase, String groupSearchFilter, String groupMembershipFilter, String managerDN, Secret managerPasswordSecret, boolean inhibitInferRootDN, boolean disableMailAddressResolver, CacheConfiguration cache, EnvironmentProperty[] environmentProperties, String displayNameAttributeName, String mailAddressAttributeName) { + this(server, rootDN, userSearchBase, userSearch, groupSearchBase, groupSearchFilter, new FromGroupSearchLDAPGroupMembershipStrategy(groupMembershipFilter), managerDN, managerPasswordSecret, inhibitInferRootDN, disableMailAddressResolver, cache, environmentProperties, displayNameAttributeName, mailAddressAttributeName); + } + + @DataBoundConstructor + public LDAPSecurityRealm(String server, String rootDN, String userSearchBase, String userSearch, String groupSearchBase, String groupSearchFilter, LDAPGroupMembershipStrategy groupMembershipStrategy, String managerDN, Secret managerPasswordSecret, boolean inhibitInferRootDN, boolean disableMailAddressResolver, CacheConfiguration cache, EnvironmentProperty[] environmentProperties, String displayNameAttributeName, String mailAddressAttributeName) { this.server = server.trim(); this.managerDN = fixEmpty(managerDN); this.managerPasswordSecret = managerPasswordSecret; @@ -415,7 +433,7 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { this.userSearch = userSearch!=null ? userSearch : DescriptorImpl.DEFAULT_USER_SEARCH; this.groupSearchBase = fixEmptyAndTrim(groupSearchBase); this.groupSearchFilter = fixEmptyAndTrim(groupSearchFilter); - this.groupMembershipFilter = fixEmptyAndTrim(groupMembershipFilter); + this.groupMembershipStrategy = groupMembershipStrategy == null ? new FromGroupSearchLDAPGroupMembershipStrategy("") : groupMembershipStrategy; this.disableMailAddressResolver = disableMailAddressResolver; this.cache = cache; this.extraEnvVars = environmentProperties == null || environmentProperties.length == 0 @@ -432,6 +450,10 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { managerPasswordSecret = Secret.fromString(Scrambler.descramble(managerPassword)); managerPassword = null; } + if (groupMembershipStrategy == null) { + groupMembershipStrategy = new FromGroupSearchLDAPGroupMembershipStrategy(groupMembershipFilter); + groupMembershipFilter = null; + } return this; } @@ -458,10 +480,15 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { return cache == null ? null : cache.getTtl(); } + @Deprecated public String getGroupMembershipFilter() { return groupMembershipFilter; } + public LDAPGroupMembershipStrategy getGroupMembershipStrategy() { + return groupMembershipStrategy; + } + public String getGroupSearchFilter() { return groupSearchFilter; } @@ -569,14 +596,13 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { ldapTemplate = new LdapTemplate(findBean(InitialDirContextFactory.class, appContext)); - if (groupMembershipFilter != null) { - AuthoritiesPopulatorImpl authoritiesPopulator = findBean(AuthoritiesPopulatorImpl.class, appContext); - authoritiesPopulator.setGroupSearchFilter(groupMembershipFilter); + if (groupMembershipStrategy != null) { + groupMembershipStrategy.setAuthoritiesPopulator(findBean(LdapAuthoritiesPopulator.class, appContext)); } return new SecurityComponents( new LDAPAuthenticationManager(findBean(AuthenticationManager.class, appContext)), - new LDAPUserDetailsService(appContext)); + new LDAPUserDetailsService(appContext, groupMembershipStrategy)); } /** @@ -712,6 +738,7 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { public static class LDAPUserDetailsService implements UserDetailsService { public final LdapUserSearch ldapSearch; public final LdapAuthoritiesPopulator authoritiesPopulator; + public final LDAPGroupMembershipStrategy groupMembershipStrategy; /** * {@link BasicAttributes} in LDAP tend to be bulky (about 20K at size), so interning them * to keep the size under control. When a programmatic client is not smart enough to @@ -720,13 +747,22 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { private final LRUMap attributesCache = new LRUMap(32); LDAPUserDetailsService(WebApplicationContext appContext) { - ldapSearch = findBean(LdapUserSearch.class, appContext); - authoritiesPopulator = findBean(LdapAuthoritiesPopulator.class, appContext); + this(appContext, null); } LDAPUserDetailsService(LdapUserSearch ldapSearch, LdapAuthoritiesPopulator authoritiesPopulator) { + this(ldapSearch, authoritiesPopulator, null); + } + + LDAPUserDetailsService(LdapUserSearch ldapSearch, LdapAuthoritiesPopulator authoritiesPopulator, LDAPGroupMembershipStrategy groupMembershipStrategy) { this.ldapSearch = ldapSearch; this.authoritiesPopulator = authoritiesPopulator; + this.groupMembershipStrategy = groupMembershipStrategy; + } + + public LDAPUserDetailsService(WebApplicationContext appContext, + LDAPGroupMembershipStrategy groupMembershipStrategy) { + this(findBean(LdapUserSearch.class, appContext), findBean(LdapAuthoritiesPopulator.class, appContext), groupMembershipStrategy); } public LdapUserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { @@ -764,9 +800,15 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { } } - GrantedAuthority[] extraAuthorities = authoritiesPopulator.getGrantedAuthorities(ldapUser); + GrantedAuthority[] extraAuthorities = groupMembershipStrategy == null + ? authoritiesPopulator.getGrantedAuthorities(ldapUser) + : groupMembershipStrategy.getGrantedAuthorities(ldapUser); for (GrantedAuthority extraAuthority : extraAuthorities) { - user.addAuthority(extraAuthority); + if (FORCE_GROUPNAME_LOWERCASE) { + user.addAuthority(new GrantedAuthorityImpl(extraAuthority.getAuthority().toLowerCase())); + } else { + user.addAuthority(extraAuthority); + } } ldapUser = user.createUserDetails(); } @@ -873,13 +915,7 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { Set names = super.getGroupMembershipRoles(userDn,username); Set r = new HashSet(names.size()*2); - if (FORCE_GROUPNAME_LOWERCASE) { - for (GrantedAuthority ga : names) { - r.add(new GrantedAuthorityImpl(ga.getAuthority().toLowerCase())); - } - } else { - r.addAll(names); - } + r.addAll(names); for (GrantedAuthority ga : names) { String role = ga.getAuthority(); @@ -954,6 +990,10 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm { return FormValidation.error(Messages.LDAPSecurityRealm_InvalidPortNumber()); } } + + public DescriptorExtensionList> getGroupMembershipStrategies() { + return Jenkins.getInstance().getDescriptorList(LDAPGroupMembershipStrategy.class); + } } /** diff --git a/src/main/java/jenkins/security/plugins/ldap/FromGroupSearchLDAPGroupMembershipStrategy.java b/src/main/java/jenkins/security/plugins/ldap/FromGroupSearchLDAPGroupMembershipStrategy.java new file mode 100644 index 0000000..7c58821 --- /dev/null +++ b/src/main/java/jenkins/security/plugins/ldap/FromGroupSearchLDAPGroupMembershipStrategy.java @@ -0,0 +1,79 @@ +/* + * The MIT License + * + * Copyright (c) 2014, Stephen Connolly + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package jenkins.security.plugins.ldap; + +import hudson.Extension; +import hudson.security.LDAPSecurityRealm; +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.providers.ldap.LdapAuthoritiesPopulator; +import org.acegisecurity.userdetails.ldap.LdapUserDetails; +import org.apache.commons.lang.StringUtils; +import org.kohsuke.stapler.DataBoundConstructor; + +/** + * Traditional strategy. + * @since 1.10 + */ +public class FromGroupSearchLDAPGroupMembershipStrategy extends LDAPGroupMembershipStrategy { + + /** + * The search filter to apply to groups. Only those groups matching this criteria will be considered as groups + * that the user belongs to. + * + * Note: we leave the default blank in case legacy users have customized their {@code LDAPBindSecurityRealm.groovy} + * as prior to 1.5 that was the only way to change the group membership filter. + */ + private final String filter; + + @DataBoundConstructor + public FromGroupSearchLDAPGroupMembershipStrategy(String filter) { + this.filter = filter; + } + + public String getFilter() { + return filter; + } + + @Override + public void setAuthoritiesPopulator(LdapAuthoritiesPopulator authoritiesPopulator) { + if (authoritiesPopulator instanceof LDAPSecurityRealm.AuthoritiesPopulatorImpl && StringUtils.isNotBlank(filter)) { + ((LDAPSecurityRealm.AuthoritiesPopulatorImpl) authoritiesPopulator).setGroupSearchFilter(filter); + } + super.setAuthoritiesPopulator(authoritiesPopulator); + } + + @Override + public GrantedAuthority[] getGrantedAuthorities(LdapUserDetails ldapUser) { + return getAuthoritiesPopulator().getGrantedAuthorities(ldapUser); + } + + @Extension + public static class DescriptorImpl extends LDAPGroupMembershipStrategyDescriptor { + + @Override + public String getDisplayName() { + return Messages.FromGroupSearchLDAPGroupMembershipStrategy_DisplayName(); + } + } +} diff --git a/src/main/java/jenkins/security/plugins/ldap/FromUserRecordLDAPGroupMembershipStrategy.java b/src/main/java/jenkins/security/plugins/ldap/FromUserRecordLDAPGroupMembershipStrategy.java new file mode 100644 index 0000000..fcdc899 --- /dev/null +++ b/src/main/java/jenkins/security/plugins/ldap/FromUserRecordLDAPGroupMembershipStrategy.java @@ -0,0 +1,97 @@ +/* + * The MIT License + * + * Copyright (c) 2014, Stephen Connolly + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package jenkins.security.plugins.ldap; + +import hudson.Extension; +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.GrantedAuthorityImpl; +import org.acegisecurity.userdetails.ldap.LdapUserDetails; +import org.kohsuke.stapler.DataBoundConstructor; + +import javax.naming.InvalidNameException; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.ldap.LdapName; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +/** + * This strategy is rumoured to work for Active Directory! + * @since 1.10 + */ +public class FromUserRecordLDAPGroupMembershipStrategy extends LDAPGroupMembershipStrategy { + + private static final Logger LOGGER = Logger.getLogger(FromUserRecordLDAPGroupMembershipStrategy.class.getName()); + private final String attributeName; + + @DataBoundConstructor + public FromUserRecordLDAPGroupMembershipStrategy(String attributeName) { + this.attributeName = attributeName; + } + + public String getAttributeName() { + return attributeName; + } + + @Override + public GrantedAuthority[] getGrantedAuthorities(LdapUserDetails ldapUser) { + List result = new ArrayList(); + Attribute attribute = ldapUser.getAttributes().get(attributeName); + if (attribute != null) { + try { + for (Object value: Collections.list(attribute.getAll())) { + String groupName = String.valueOf(value); + try { + LdapName dn = new LdapName(groupName); + groupName = String.valueOf(dn.getRdn(dn.size() - 1).getValue()); + } catch (InvalidNameException e) { + LOGGER.log(Level.FINEST, "Expected a Group DN but found: {0}", groupName); + } + result.add(new GrantedAuthorityImpl(groupName)); + } + } catch (NamingException e) { + LogRecord lr = new LogRecord(Level.FINE, + "Failed to retrieve member of attribute ({0}) from LDAP user details"); + lr.setThrown(e); + lr.setParameters(new Object[]{attributeName}); + LOGGER.log(lr); + } + + } + return result.toArray(new GrantedAuthority[result.size()]); + } + + @Extension + public static class DescriptorImpl extends LDAPGroupMembershipStrategyDescriptor { + + @Override + public String getDisplayName() { + return Messages.FromUserRecordLDAPGroupMembershipStrategy_DisplayName(); + } + } +} \ No newline at end of file diff --git a/src/main/java/jenkins/security/plugins/ldap/LDAPGroupMembershipStrategy.java b/src/main/java/jenkins/security/plugins/ldap/LDAPGroupMembershipStrategy.java new file mode 100644 index 0000000..5ecefb9 --- /dev/null +++ b/src/main/java/jenkins/security/plugins/ldap/LDAPGroupMembershipStrategy.java @@ -0,0 +1,67 @@ +/* + * The MIT License + * + * Copyright (c) 2014, Stephen Connolly + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package jenkins.security.plugins.ldap; + +import hudson.model.AbstractDescribableImpl; +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.providers.ldap.LdapAuthoritiesPopulator; +import org.acegisecurity.userdetails.ldap.LdapUserDetails; + +/** + * A strategy for determining the groups that a user belongs to. + * + * @since 1.10 + */ +public abstract class LDAPGroupMembershipStrategy extends AbstractDescribableImpl { + /** + * The standard group member of searcher. + */ + private transient LdapAuthoritiesPopulator authoritiesPopulator; + + /** + * The {@link LdapAuthoritiesPopulator} to use if performing a traditional search. + * + * @return The {@link LdapAuthoritiesPopulator} to use if performing a traditional search. + */ + public LdapAuthoritiesPopulator getAuthoritiesPopulator() { + return authoritiesPopulator; + } + + /** + * Override this method if you want to change the configuration of the {@link LdapAuthoritiesPopulator}. + * + * @param authoritiesPopulator the {@link LdapAuthoritiesPopulator} to use (and abuse). + */ + public void setAuthoritiesPopulator(LdapAuthoritiesPopulator authoritiesPopulator) { + this.authoritiesPopulator = authoritiesPopulator; + } + + /** + * Returns the {@link GrantedAuthority}s that the specified user belongs to. + * + * @param ldapUser the specified user. + * @return the {@link GrantedAuthority}s that the specified user belongs to. + */ + public abstract GrantedAuthority[] getGrantedAuthorities(LdapUserDetails ldapUser); +} diff --git a/src/main/java/jenkins/security/plugins/ldap/LDAPGroupMembershipStrategyDescriptor.java b/src/main/java/jenkins/security/plugins/ldap/LDAPGroupMembershipStrategyDescriptor.java new file mode 100644 index 0000000..6cbadbc --- /dev/null +++ b/src/main/java/jenkins/security/plugins/ldap/LDAPGroupMembershipStrategyDescriptor.java @@ -0,0 +1,33 @@ +/* + * The MIT License + * + * Copyright (c) 2014, Stephen Connolly + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package jenkins.security.plugins.ldap; + +import hudson.model.Descriptor; + +/** + * The base {@link Descriptor} class for {@link LDAPGroupMembershipStrategy}. + * @since 1.10 + */ +public abstract class LDAPGroupMembershipStrategyDescriptor extends Descriptor { +} diff --git a/src/main/resources/hudson/security/LDAPSecurityRealm/config.jelly b/src/main/resources/hudson/security/LDAPSecurityRealm/config.jelly index 64a4b5f..f3fdd23 100644 --- a/src/main/resources/hudson/security/LDAPSecurityRealm/config.jelly +++ b/src/main/resources/hudson/security/LDAPSecurityRealm/config.jelly @@ -46,8 +46,8 @@ THE SOFTWARE. - - + + diff --git a/src/main/resources/jenkins/security/plugins/ldap/FromGroupSearchLDAPGroupMembershipStrategy/config.jelly b/src/main/resources/jenkins/security/plugins/ldap/FromGroupSearchLDAPGroupMembershipStrategy/config.jelly new file mode 100644 index 0000000..791acbf --- /dev/null +++ b/src/main/resources/jenkins/security/plugins/ldap/FromGroupSearchLDAPGroupMembershipStrategy/config.jelly @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/src/main/resources/jenkins/security/plugins/ldap/FromUserRecordLDAPGroupMembershipStrategy/config.jelly b/src/main/resources/jenkins/security/plugins/ldap/FromUserRecordLDAPGroupMembershipStrategy/config.jelly new file mode 100644 index 0000000..1926c80 --- /dev/null +++ b/src/main/resources/jenkins/security/plugins/ldap/FromUserRecordLDAPGroupMembershipStrategy/config.jelly @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/src/main/resources/jenkins/security/plugins/ldap/Messages.properties b/src/main/resources/jenkins/security/plugins/ldap/Messages.properties new file mode 100644 index 0000000..c6c5e6d --- /dev/null +++ b/src/main/resources/jenkins/security/plugins/ldap/Messages.properties @@ -0,0 +1,2 @@ +FromUserRecordLDAPGroupMembershipStrategy.DisplayName=Parse user attribute for list of groups +FromGroupSearchLDAPGroupMembershipStrategy.DisplayName=Search for groups containing user \ No newline at end of file diff --git a/src/test/java/hudson/security/LDAPSecurityRealm_Test.java b/src/test/java/hudson/security/LDAPSecurityRealm_Test.java index d82a5e8..bab6b73 100644 --- a/src/test/java/hudson/security/LDAPSecurityRealm_Test.java +++ b/src/test/java/hudson/security/LDAPSecurityRealm_Test.java @@ -25,7 +25,11 @@ package hudson.security; import java.util.Collections; + +import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; + +import jenkins.security.plugins.ldap.FromGroupSearchLDAPGroupMembershipStrategy; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; @@ -50,7 +54,9 @@ public class LDAPSecurityRealm_Test { // different name so as not to clash with assertEquals("uS", sr.userSearch); assertEquals("gSB", sr.groupSearchBase); assertEquals("gSF", sr.groupSearchFilter); - assertEquals("gMF", sr.groupMembershipFilter); + assertThat(sr.getGroupMembershipStrategy(), instanceOf(FromGroupSearchLDAPGroupMembershipStrategy.class)); + assertThat(((FromGroupSearchLDAPGroupMembershipStrategy)sr.getGroupMembershipStrategy()).getFilter(), is("gMF")); + assertNull(sr.groupMembershipFilter); assertEquals("mDN", sr.managerDN); assertEquals("s3cr3t", sr.getManagerPassword()); assertTrue(sr.inhibitInferRootDN);