XNAT-5653 Added ability to handle no configured properties for LDAP provider.

This commit is contained in:
Rick Herrick 2018-06-14 18:12:33 -05:00
parent 5ac0f126b4
commit af723cbc37
3 changed files with 76 additions and 41 deletions

View file

@ -108,6 +108,7 @@ dependencies {
implementation localGroovy()
compileOnly "com.google.code.findbugs:jsr305"
compileOnly "org.apache.ivy:ivy:2.4.0"
compileOnly("stratum:stratum") {
transitive = false

View file

@ -15,13 +15,16 @@ import org.nrg.xdat.XDAT;
import org.nrg.xdat.preferences.SiteConfigPreferences;
import org.nrg.xdat.services.XdatUserAuthService;
import org.nrg.xft.security.UserI;
import org.nrg.xnat.auth.ldap.XnatLdapUserDetailsMapper;
import org.nrg.xnat.auth.ldap.tokens.XnatLdapUsernamePasswordAuthenticationToken;
import org.nrg.xnat.security.provider.ProviderAttributes;
import org.nrg.xnat.security.provider.XnatAuthenticationProvider;
import org.nrg.xnat.security.tokens.XnatAuthenticationToken;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.ProviderNotFoundException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
@ -33,6 +36,7 @@ import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
import org.springframework.stereotype.Component;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@ -46,25 +50,29 @@ public class XnatLdapAuthenticationProvider extends LdapAuthenticationProvider i
public static final String LDAP_VALIDATE_USERNAME = "validate.username";
public static final String LDAP_VALIDATE_PASSWORD = "validate.password";
public XnatLdapAuthenticationProvider(final ProviderAttributes attributes) {
super(getBindAuthenticator(attributes));
_attributes = attributes;
public XnatLdapAuthenticationProvider(final ProviderAttributes attributes, final XdatUserAuthService userAuthService, final SiteConfigPreferences preferences) {
this(attributes, getLdapAuthenticator(attributes), getContextMapper(attributes, userAuthService, preferences));
}
public XnatLdapAuthenticationProvider(final ProviderAttributes attributes, final LdapAuthenticator authenticator, final UserDetailsContextMapper contextMapper) {
super(authenticator);
setUserDetailsContextMapper(contextMapper);
setProviderId(attributes.getProviderId());
setName(attributes.getName());
setVisible(attributes.isVisible());
setAutoEnabled(attributes.isAutoEnabled());
setAutoVerified(attributes.isAutoVerified());
if (contextMapper != null) {
setUserDetailsContextMapper(contextMapper);
}
_attributes = attributes;
}
protected XnatLdapAuthenticationProvider(final List<ProviderAttributes> attributesList, final XdatUserAuthService userAuthService, final SiteConfigPreferences preferences) {
this(getPrimaryAttributes(attributesList), userAuthService, preferences);
}
@Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
final Authentication processed = super.authenticate(authentication);
@ -229,21 +237,49 @@ public class XnatLdapAuthenticationProvider extends LdapAuthenticationProvider i
return getName();
}
protected static BindAuthenticator getBindAuthenticator(final ProviderAttributes provider) {
final DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(provider.getProperty(LDAP_ADDRESS));
contextSource.setUserDn(provider.getProperty(LDAP_USERDN));
contextSource.setPassword(provider.getProperty(LDAP_PASSWORD));
contextSource.afterPropertiesSet();
final BindAuthenticator ldapBindAuthenticator = new BindAuthenticator(contextSource);
ldapBindAuthenticator.setUserSearch(new FilterBasedLdapUserSearch(provider.getProperty(LDAP_SEARCH_BASE), provider.getProperty(LDAP_SEARCH_FILTER), contextSource));
return ldapBindAuthenticator;
}
protected ProviderAttributes getAttributes() {
return _attributes;
}
private static ProviderAttributes getPrimaryAttributes(final List<ProviderAttributes> attributesList) {
return attributesList.isEmpty() ? NULL_ATTRIBUTES : attributesList.get(0);
}
@Nonnull
private static LdapAuthenticator getLdapAuthenticator(@Nonnull final ProviderAttributes attributes) {
if (StringUtils.equals(NULL_PROVIDER, attributes.getProviderId())) {
return getNullAuthenticator();
}
final DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(attributes.getProperty(LDAP_ADDRESS));
contextSource.setUserDn(attributes.getProperty(LDAP_USERDN));
contextSource.setPassword(attributes.getProperty(LDAP_PASSWORD));
contextSource.afterPropertiesSet();
final BindAuthenticator ldapBindAuthenticator = new BindAuthenticator(contextSource);
ldapBindAuthenticator.setUserSearch(new FilterBasedLdapUserSearch(attributes.getProperty(LDAP_SEARCH_BASE), attributes.getProperty(LDAP_SEARCH_FILTER), contextSource));
return ldapBindAuthenticator;
}
private static LdapAuthenticator getNullAuthenticator() {
return new LdapAuthenticator() {
@Override
public DirContextOperations authenticate(final Authentication authentication) {
throw new ProviderNotFoundException("There is no valid LDAP service configured.");
}
};
}
private static UserDetailsContextMapper getContextMapper(final ProviderAttributes attributes, final XdatUserAuthService userAuthService, final SiteConfigPreferences preferences) {
if (StringUtils.equals(NULL_PROVIDER, attributes.getProviderId())) {
return null;
}
return new XnatLdapUserDetailsMapper(attributes.getProviderId(), userAuthService, preferences, attributes.getProperties());
}
private static final String NULL_PROVIDER = "null-ldap-provider";
private static final ProviderAttributes NULL_ATTRIBUTES = new ProviderAttributes(NULL_PROVIDER, XdatUserAuthService.LDAP, NULL_PROVIDER, false, false, false, null);
private final ProviderAttributes _attributes;
private String _displayName = "";

View file

@ -9,11 +9,11 @@
package org.nrg.xnat.auth.ldap.provider;
import com.google.common.collect.ImmutableList;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nrg.xdat.preferences.SiteConfigPreferences;
import org.nrg.xdat.services.XdatUserAuthService;
import org.nrg.xnat.auth.ldap.XnatLdapUserDetailsMapper;
import org.nrg.xnat.auth.ldap.tokens.XnatLdapUsernamePasswordAuthenticationToken;
import org.nrg.xnat.security.provider.AuthenticationProviderConfigurationLocator;
import org.nrg.xnat.security.provider.ProviderAttributes;
@ -25,6 +25,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import javax.annotation.Nonnull;
import java.util.*;
import static org.nrg.xdat.services.XdatUserAuthService.LDAP;
@ -39,35 +40,29 @@ import static org.nrg.xdat.services.XdatUserAuthService.LDAP;
public class XnatMulticonfigLdapAuthenticationProvider extends XnatLdapAuthenticationProvider implements XnatMulticonfigAuthenticationProvider {
@Autowired
public XnatMulticonfigLdapAuthenticationProvider(final AuthenticationProviderConfigurationLocator locator, final XdatUserAuthService userAuthService, final SiteConfigPreferences preferences) {
this(locator.getProviderDefinitionsByType(LDAP), userAuthService, preferences);
this(locator.getProviderDefinitionsByAuthMethod(LDAP), userAuthService, preferences);
}
public XnatMulticonfigLdapAuthenticationProvider(final Map<String, ProviderAttributes> definitions, final XdatUserAuthService userAuthService, final SiteConfigPreferences preferences) {
super(getOrderedConfigurations(definitions).get(0));
super(getOrderedConfigurations(definitions), userAuthService, preferences);
// If there are no definitions or there's only one definition, that's handled in the superclass, so
// we can skip the following initialization.
if (definitions != null && definitions.size() > 1) {
final List<ProviderAttributes> configurations = getOrderedConfigurations(definitions);
// We've already initialized the super class with the primary bind authenticator, now we just need to
// We've already initialized the super class with the first ordered configuration. Now we just need to
// set the remaining provider properties for this instance. All of the other providers go into the map.
final ProviderAttributes primary = configurations.remove(0);
final String primaryProviderId = primary.getProviderId();
setProviderId(primaryProviderId);
setName(primary.getName());
setVisible(primary.isVisible());
setAutoEnabled(primary.isAutoEnabled());
setAutoVerified(primary.isAutoVerified());
setUserDetailsContextMapper(new XnatLdapUserDetailsMapper(primaryProviderId, userAuthService, preferences, primary.getProperties()));
_providerIds.add(primaryProviderId);
_providerAttributes.put(primaryProviderId, primary);
for (final ProviderAttributes attributes : configurations) {
final String providerId = attributes.getProviderId();
_providerIds.add(providerId);
_providerAttributes.put(providerId, attributes);
_providers.put(providerId, new XnatLdapAuthenticationProvider(attributes, getBindAuthenticator(attributes), new XnatLdapUserDetailsMapper(providerId, userAuthService, preferences, attributes.getProperties())));
_providers.put(providerId, new XnatLdapAuthenticationProvider(attributes, userAuthService, preferences));
}
}
}
@ -100,7 +95,7 @@ public class XnatMulticonfigLdapAuthenticationProvider extends XnatLdapAuthentic
*/
@Override
public List<String> getProviderIds() {
return _providerIds;
return ImmutableList.copyOf(_providerAttributes.keySet());
}
@Override
@ -244,7 +239,11 @@ public class XnatMulticonfigLdapAuthenticationProvider extends XnatLdapAuthentic
return getName();
}
@Nonnull
private static List<ProviderAttributes> getOrderedConfigurations(final Map<String, ProviderAttributes> definitions) {
if (definitions == null || definitions.isEmpty()) {
return Collections.emptyList();
}
final List<ProviderAttributes> configurations = new ArrayList<>();
for (final String key : new LinkedList<>(definitions.keySet())) {
configurations.add(definitions.get(key));
@ -252,7 +251,6 @@ public class XnatMulticonfigLdapAuthenticationProvider extends XnatLdapAuthentic
return configurations;
}
private final List<String> _providerIds = new ArrayList<>();
private final Map<String, ProviderAttributes> _providerAttributes = new HashMap<>();
private final Map<String, XnatLdapAuthenticationProvider> _providers = new HashMap<>();