/*
 * 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.server.security.authorization;

import java.util.Collection;
import java.util.List;

import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider;
import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
import org.apache.ambari.server.orm.entities.UserEntity;
import org.apache.ambari.server.security.ClientSecurityType;
import org.apache.ambari.server.security.authentication.AccountDisabledException;
import org.apache.ambari.server.security.authentication.AmbariAuthenticationProvider;
import org.apache.ambari.server.security.authentication.AmbariUserAuthentication;
import org.apache.ambari.server.security.authentication.AmbariUserDetails;
import org.apache.ambari.server.security.authentication.InvalidUsernamePasswordCombinationException;
import org.apache.ambari.server.security.authentication.TooManyLoginFailuresException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
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 org.springframework.security.ldap.userdetails.LdapUserDetails;

import com.google.inject.Inject;


/**
 * Provides LDAP user authorization logic for Ambari Server
 */
public class AmbariLdapAuthenticationProvider extends AmbariAuthenticationProvider {
  private static final String SYSTEM_PROPERTY_DISABLE_ENDPOINT_IDENTIFICATION = "com.sun.jndi.ldap.object.disableEndpointIdentification";
  private static Logger LOG = LoggerFactory.getLogger(AmbariLdapAuthenticationProvider.class);

  final AmbariLdapConfigurationProvider ldapConfigurationProvider;

  private AmbariLdapAuthoritiesPopulator authoritiesPopulator;

  private ThreadLocal<LdapServerProperties> ldapServerProperties = new ThreadLocal<>();
  private ThreadLocal<LdapAuthenticationProvider> providerThreadLocal = new ThreadLocal<>();
  private ThreadLocal<String> ldapUserSearchFilterThreadLocal = new ThreadLocal<>();

  @Inject
  public AmbariLdapAuthenticationProvider(Users users, Configuration configuration, AmbariLdapConfigurationProvider ldapConfigurationProvider,
                                          AmbariLdapAuthoritiesPopulator authoritiesPopulator) {
    super(users, configuration);
    this.ldapConfigurationProvider = ldapConfigurationProvider;
    this.authoritiesPopulator = authoritiesPopulator;
  }

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    if (isLdapEnabled()) {
      if (authentication.getName() == null) {
        LOG.info("Authentication failed: no username provided");
        throw new InvalidUsernamePasswordCombinationException("");
      }

      String username = authentication.getName().trim();

      if (authentication.getCredentials() == null) {
        LOG.info("Authentication failed: no credentials provided: {}", username);
        throw new InvalidUsernamePasswordCombinationException(username);
      }

      try {
        Authentication auth = loadLdapAuthenticationProvider(username).authenticate(authentication);
        UserEntity userEntity = getUserEntity(auth);

        if (userEntity == null) {
          // TODO: If we were automatically importing accounts from the LDAP server, we should
          // TODO: probably do it here.
          LOG.debug("user not found ('{}')", username);
          throw new InvalidUsernamePasswordCombinationException(username);
        } else {
          Users users = getUsers();

          // Ensure the user is allowed to login....
          try {
            users.validateLogin(userEntity, username);
          } catch (AccountDisabledException | TooManyLoginFailuresException e) {
            if (getConfiguration().showLockedOutUserMessage()) {
              throw e;
            } else {
              // Do not give away information about the existence or status of a user
              throw new InvalidUsernamePasswordCombinationException(username, false, e);
            }
          }

          AmbariUserDetails userDetails = new AmbariUserDetails(users.getUser(userEntity), null, users.getUserAuthorities(userEntity));
          return new AmbariUserAuthentication(null, userDetails, true);
        }
      } catch (AuthenticationException e) {
        LOG.debug("Got exception during LDAP authentication attempt", e);
        // Try to help in troubleshooting
        Throwable cause = e.getCause();
        if ((cause != null) && (cause != e)) {
          // Below we check the cause of an AuthenticationException to see what the actual cause is
          // and then send an appropriate message to the caller.
          if (cause instanceof org.springframework.ldap.CommunicationException) {
            if (LOG.isDebugEnabled()) {
              LOG.warn("Failed to communicate with the LDAP server: " + cause.getMessage(), e);
            } else {
              LOG.warn("Failed to communicate with the LDAP server: " + cause.getMessage());
            }
          } else if (cause instanceof org.springframework.ldap.AuthenticationException) {
            LOG.warn("Looks like LDAP manager credentials (that are used for " +
                "connecting to LDAP server) are invalid.", e);
          }
        }
        throw new InvalidUsernamePasswordCombinationException(username, e);
      } catch (IncorrectResultSizeDataAccessException multipleUsersFound) {
        String message = ldapConfigurationProvider.get().isLdapAlternateUserSearchEnabled()
            ? String.format("Login Failed: Please append your domain to your username and try again.  Example: %s@domain", username)
            : "Login Failed: More than one user with that username found, please work with your Ambari Administrator to adjust your LDAP configuration";

        throw new DuplicateLdapUserFoundAuthenticationException(message);
      }
    } else {
      return null;
    }
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
  }

  /**
   * Reloads LDAP Context Source and depending objects if properties were changed
   *
   * @return corresponding LDAP authentication provider
   */
  LdapAuthenticationProvider loadLdapAuthenticationProvider(String userName) {
    boolean ldapConfigPropertiesChanged = reloadLdapServerProperties();

    String ldapUserSearchFilter = getLdapUserSearchFilter(userName);

    if (ldapConfigPropertiesChanged || !ldapUserSearchFilter.equals(ldapUserSearchFilterThreadLocal.get())) {

      LOG.info("Either LDAP Properties or user search filter changed - rebuilding Context");
      LdapContextSource springSecurityContextSource = new LdapContextSource();
      List<String> ldapUrls = ldapServerProperties.get().getLdapUrls();
      springSecurityContextSource.setUrls(ldapUrls.toArray(new String[ldapUrls.size()]));
      springSecurityContextSource.setBase(ldapServerProperties.get().getBaseDN());

      if (!ldapServerProperties.get().isAnonymousBind()) {
        springSecurityContextSource.setUserDn(ldapServerProperties.get().getManagerDn());
        springSecurityContextSource.setPassword(ldapServerProperties.get().getManagerPassword());
      }

      if (ldapServerProperties.get().isUseSsl() && ldapServerProperties.get().isDisableEndpointIdentification()) {
        System.setProperty(SYSTEM_PROPERTY_DISABLE_ENDPOINT_IDENTIFICATION, "true");
        LOG.info("Disabled endpoint identification");
      } else {
        System.clearProperty(SYSTEM_PROPERTY_DISABLE_ENDPOINT_IDENTIFICATION);
        LOG.info("Removed endpoint identification disabling");
      }

      try {
        springSecurityContextSource.afterPropertiesSet();
      } catch (Exception e) {
        LOG.error("LDAP Context Source not loaded ", e);
        throw new UsernameNotFoundException("LDAP Context Source not loaded", e);
      }

      //TODO change properties
      String userSearchBase = ldapServerProperties.get().getUserSearchBase();
      FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch(userSearchBase, ldapUserSearchFilter, springSecurityContextSource);

      AmbariLdapBindAuthenticator bindAuthenticator = new AmbariLdapBindAuthenticator(springSecurityContextSource, ldapConfigurationProvider.get());
      bindAuthenticator.setUserSearch(userSearch);

      LdapAuthenticationProvider authenticationProvider = new LdapAuthenticationProvider(bindAuthenticator, authoritiesPopulator);
      providerThreadLocal.set(authenticationProvider);
    }

    ldapUserSearchFilterThreadLocal.set(ldapUserSearchFilter);

    return providerThreadLocal.get();
  }


  /**
   * Check if LDAP authentication is enabled in server properties
   *
   * @return true if enabled
   */
  boolean isLdapEnabled() {
    return getConfiguration().getClientSecurityType() == ClientSecurityType.LDAP;
  }

  /**
   * Reloads LDAP Server properties from configuration
   *
   * @return true if properties were reloaded
   */
  private boolean reloadLdapServerProperties() {
    LdapServerProperties properties = ldapConfigurationProvider.get().getLdapServerProperties();
    if (!properties.equals(ldapServerProperties.get())) {
      LOG.info("Reloading properties");
      ldapServerProperties.set(properties);
      return true;
    }
    return false;
  }


  private String getLdapUserSearchFilter(String userName) {
    return ldapServerProperties.get()
        .getUserSearchFilter(ldapConfigurationProvider.get().isLdapAlternateUserSearchEnabled() && AmbariLdapUtils.isUserPrincipalNameFormat(userName));
  }

  /**
   * Gets the {@link UserEntity} related to the authentication information
   * <p>
   * First the DN is retrieved from the user authentication information and a {@link UserAuthenticationEntity}
   * is queried for where the type value is LDAP and key value case-insensitively matches the DN.
   * If a record is found, the related {@link UserEntity} is returned.
   * <p>
   * Else, a {@link UserEntity} with the user name is queried. If one is found and it has a
   * {@link UserAuthenticationEntity} where the type value is LDAP and key is empty, the related
   * {@link UserEntity} is returned
   * <p>
   * Else, <code>null</code> is returned.
   *
   * @param authentication the user's authentication data
   * @return a {@link UserEntity}
   */
  private UserEntity getUserEntity(Authentication authentication) {
    UserEntity userEntity = null;

    // Find user with the matching DN
    String dn = getUserDN(authentication);
    if (!StringUtils.isEmpty(dn)) {
      userEntity = getUserEntityForDN(dn);
    }

    // If a user was not found with the exact authentication properties (LDAP/dn), look up the user
    // using the configured LDAP username attribute and ensure that user has an empty-keyed LDAP
    // authentication entity record.
    if (userEntity == null) {
      String userName = AuthorizationHelper.resolveLoginAliasToUserName(authentication.getName());
      userEntity = getUsers().getUserEntity(userName);

      if (userEntity != null) {
        Collection<UserAuthenticationEntity> authenticationEntities = getAuthenticationEntities(userEntity, UserAuthenticationType.LDAP);
        UserEntity _userEntity = userEntity; // Hold on to the user entity value for now.
        userEntity = null;  // Guilty until proven innocent

        if (!CollectionUtils.isEmpty(authenticationEntities)) {
          for (UserAuthenticationEntity entity : authenticationEntities) {
            if (StringUtils.isEmpty(entity.getAuthenticationKey())) {
              // Proven innocent!
              userEntity = _userEntity;
              break;
            }
          }
        }
      }
    }

    return userEntity;
  }

  /**
   * Given a DN from the LDAP server, find the owning UserEntity.
   * <p>
   * DNs are case sensitive. Internally they are execpted to be stored as the bytes of the lowercase
   * string.
   * <p>
   * DN's are expected to be unique across all {@link UserAuthenticationEntity} records for type
   * UserAuthenticationType.LDAP.
   *
   * @param dn the DN to search for
   * @return a {@link UserEntity}, if found
   */
  private UserEntity getUserEntityForDN(String dn) {
    Collection<UserAuthenticationEntity> authenticationEntities = getAuthenticationEntities(UserAuthenticationType.LDAP, StringUtils.lowerCase(dn));
    return ((authenticationEntities == null) || (authenticationEntities.size() != 1))
        ? null
        : authenticationEntities.iterator().next().getUser();
  }

  /**
   * Given the authentication object, attempt to retrieve the user's DN value from it.
   *
   * @param authentication the authentication data
   * @return the relative DN; else <code>null</code> if not available
   */
  private String getUserDN(Authentication authentication) {
    Object objectPrincipal = (authentication == null) ? null : authentication.getPrincipal();
    if (objectPrincipal instanceof LdapUserDetails) {
      return ((LdapUserDetails) objectPrincipal).getDn();
    }

    return null;
  }
}
