/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* http://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.apache.ambari.logsearch.web.security;
import java.util.List;
import org.apache.ambari.logsearch.conf.AuthPropsConfig;
import org.apache.log4j.Logger;
import org.springframework.ldap.CommunicationException;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class LogsearchLdapAuthenticationProvider extends
LogsearchAbstractAuthenticationProvider {
private static Logger logger = Logger
.getLogger(LogsearchLdapAuthenticationProvider.class);
private static LdapProperties ldapServerProperties = null;
private static LdapAuthenticationProvider ldapAuthProvider = null;
private String logStatement = "";
@Inject
private AuthPropsConfig authPropsConfig;
public LogsearchLdapAuthenticationProvider() {
}
@PostConstruct
public void postConstruct() {
logger.debug("Creating object of ldap auth provider ");
if (authPropsConfig.isAuthLdapEnabled()) {
ldapAuthProvider = loadLdapAuthenticationProvider();
} else {
logger.info("Ldap auth is disabled");
}
}
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
if (!authPropsConfig.isAuthLdapEnabled()) {
logger.debug("Ldap auth is disabled");
return authentication;
}
try {
LdapAuthenticationProvider authProvider = loadLdapAuthenticationProvider();
if (authProvider != null) {
return authProvider.authenticate(authentication);
} else {
return authentication;
}
} catch (AuthenticationException e) {
logger.info("Got exception during LDAP authentication attempt", e);
// Try to help in troubleshooting
Throwable cause = e.getCause();
if (cause != null) {
if ((cause != e)
&& (cause instanceof org.springframework.ldap.AuthenticationException)) {
logger.warn(
"Looks like LDAP manager credentials (that are used for "
+ "connecting to LDAP server) are invalid.",
e);
}
}
} catch (CommunicationException e) {
logger.error(e);
} catch (Exception e) {
logger.error(e, e.getCause());
}
if (authentication != null && !authentication.isAuthenticated()) {
logger.warn("Ldap authentication failed. username="
+ authentication.getName() + ", details="
+ authentication.getDetails());
throw new BadCredentialsException("Invalid credentials!!");
}
return authentication;
}
/**
* Reloads LDAP Context Source and depending objects if properties were
* changed
*
* @return corresponding LDAP authentication provider
*/
private LdapAuthenticationProvider loadLdapAuthenticationProvider() {
if (reloadLdapServerProperties()) {
logger.info("LDAP Properties changed - rebuilding Context");
LdapContextSource springSecurityContextSource = new LdapContextSource();
List<String> ldapUrls = ldapServerProperties.getLdapUrls();
logStatement = "ldapUrls=" + ldapUrls;
if (ldapUrls == null || ldapUrls.size() == 0) {
logger.info("LDAP URL is empty. So won't initialize LDAP provider");
return null;
}
springSecurityContextSource.setUrls(ldapUrls
.toArray(new String[ldapUrls.size()]));
springSecurityContextSource.setBase(ldapServerProperties
.getBaseDN());
logStatement = logStatement + ", baseDN="
+ ldapServerProperties.getBaseDN();
if (!ldapServerProperties.isAnonymousBind()) {
springSecurityContextSource.setUserDn(ldapServerProperties
.getManagerDn());
logStatement = logStatement + ", managerDN="
+ ldapServerProperties.getManagerDn();
springSecurityContextSource.setPassword(ldapServerProperties
.getManagerPassword());
}
try {
springSecurityContextSource.afterPropertiesSet();
} catch (Exception e) {
logger.error("LDAP Context Source not loaded ", e);
throw new UsernameNotFoundException(
"LDAP Context Source not loaded. ldapDetails="
+ logStatement, e);
}
String userSearchBase = ldapServerProperties.getUserSearchBase();
logStatement = logStatement + ", userSearchBase=" + userSearchBase;
String userSearchFilter = ldapServerProperties
.getUserSearchFilter();
logStatement = logStatement + ", userSearchFilter="
+ userSearchFilter;
logger.info("LDAP properties=" + logStatement);
FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch(
userSearchBase, userSearchFilter,
springSecurityContextSource);
LogsearchLdapBindAuthenticator bindAuthenticator = new LogsearchLdapBindAuthenticator(
springSecurityContextSource, ldapServerProperties);
bindAuthenticator.setUserSearch(userSearch);
LdapAuthenticationProvider authenticationProvider = new LdapAuthenticationProvider(
bindAuthenticator);
ldapAuthProvider = authenticationProvider;
}
return ldapAuthProvider;
}
/**
* Reloads LDAP Server properties from configuration
*
* @return true if properties were reloaded
*/
private boolean reloadLdapServerProperties() {
LdapProperties properties = LdapUtil.loadLdapProperties();
if (!properties.equals(ldapServerProperties)) {
logger.info("Reloading properties");
ldapServerProperties = properties;
return true;
}
return false;
}
}