/*
 * 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.serveraction.kerberos;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.ambari.server.utils.ShellCommandUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;

/**
 * MITKerberosOperationHandler is an implementation of a KerberosOperationHandler providing
 * functionality specifically for an MIT KDC. See http://web.mit.edu/kerberos.
 * <p/>
 * It is assumed that a MIT Kerberos client is installed and that the kdamin shell command is
 * available
 */
public class MITKerberosOperationHandler extends KDCKerberosOperationHandler {

  private final static Logger LOG = LoggerFactory.getLogger(MITKerberosOperationHandler.class);

  @Inject
  private Configuration configuration;

  /**
   * A String containing user-specified attributes used when creating principals
   */
  private String createAttributes = null;

  /**
   * A String containing the resolved path to the kdamin executable
   */
  private String executableKadmin = null;

  /**
   * Prepares and creates resources to be used by this KerberosOperationHandler
   * <p/>
   * It is expected that this KerberosOperationHandler will not be used before this call.
   * <p/>
   * The kerberosConfiguration Map is not being used.
   *
   * @param administratorCredentials a PrincipalKeyCredential containing the administrative credential
   *                                 for the relevant KDC
   * @param realm                    a String declaring the default Kerberos realm (or domain)
   * @param kerberosConfiguration    a Map of key/value pairs containing data from the kerberos-env configuration set
   * @throws KerberosKDCConnectionException       if a connection to the KDC cannot be made
   * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
   * @throws KerberosRealmException               if the realm does not map to a KDC
   * @throws KerberosOperationException           if an unexpected error occurred
   */
  @Override
  public void open(PrincipalKeyCredential administratorCredentials, String realm, Map<String, String> kerberosConfiguration)
      throws KerberosOperationException {

    if (kerberosConfiguration != null) {
      createAttributes = kerberosConfiguration.get(KERBEROS_ENV_KDC_CREATE_ATTRIBUTES);
    }

    // Pre-determine the paths to relevant Kerberos executables
    executableKadmin = getExecutable("kadmin");

    super.open(administratorCredentials, realm, kerberosConfiguration);
  }

  @Override
  public void close() throws KerberosOperationException {
    createAttributes = null;
    executableKadmin = null;

    super.close();
  }

  /**
   * Test to see if the specified principal exists in a previously configured MIT KDC
   * <p/>
   * This implementation creates a query to send to the kadmin shell command and then interrogates
   * the result from STDOUT to determine if the presence of the specified principal.
   *
   * @param principal a String containing the principal to test
   * @param service   a boolean value indicating whether the principal is for a service or not
   * @return true if the principal exists; false otherwise
   * @throws KerberosKDCConnectionException       if a connection to the KDC cannot be made
   * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
   * @throws KerberosRealmException               if the realm does not map to a KDC
   * @throws KerberosOperationException           if an unexpected error occurred
   */
  @Override
  public boolean principalExists(String principal, boolean service)
      throws KerberosOperationException {

    if (!isOpen()) {
      throw new KerberosOperationException("This operation handler has not been opened");
    }

    if (!StringUtils.isEmpty(principal)) {
      // Create the KAdmin query to execute:
      ShellCommandUtil.Result result = invokeKAdmin(String.format("get_principal %s", principal));

      // If there is data from STDOUT, see if the following string exists:
      //    Principal: <principal>
      String stdOut = result.getStdout();
      return (stdOut != null) && stdOut.contains(String.format("Principal: %s", principal));
    }

    return false;
  }

  /**
   * Creates a new principal in a previously configured MIT KDC
   * <p/>
   * This implementation creates a query to send to the kadmin shell command and then interrogates
   * the result from STDOUT to determine if the operation executed successfully.
   *
   * @param principal a String containing the principal add
   * @param password  a String containing the password to use when creating the principal
   * @param service   a boolean value indicating whether the principal is to be created as a service principal or not
   * @return an Integer declaring the generated key number
   * @throws KerberosKDCConnectionException          if a connection to the KDC cannot be made
   * @throws KerberosAdminAuthenticationException    if the administrator credentials fail to authenticate
   * @throws KerberosRealmException                  if the realm does not map to a KDC
   * @throws KerberosPrincipalAlreadyExistsException if the principal already exists
   * @throws KerberosOperationException              if an unexpected error occurred
   */
  @Override
  public Integer createPrincipal(String principal, String password, boolean service)
      throws KerberosOperationException {

    if (!isOpen()) {
      throw new KerberosOperationException("This operation handler has not been opened");
    }

    if (StringUtils.isEmpty(principal)) {
      throw new KerberosOperationException("Failed to create new principal - no principal specified");
    }

    // Create the kdamin query:  add_principal <-randkey|-pw <password>> [<options>] <principal>
    ShellCommandUtil.Result result = invokeKAdmin(String.format("add_principal -randkey %s %s",
        (createAttributes == null) ? "" : createAttributes, principal));

    // If there is data from STDOUT, see if the following string exists:
    //    Principal "<principal>" created
    String stdOut = result.getStdout();
    String stdErr = result.getStderr();
    if ((stdOut != null) && stdOut.contains(String.format("Principal \"%s\" created", principal))) {
      return 0;
    } else if ((stdErr != null) && stdErr.contains(String.format("Principal or policy already exists while creating \"%s\"", principal))) {
      throw new KerberosPrincipalAlreadyExistsException(principal);
    } else {
      LOG.error("Failed to execute kadmin query: add_principal -pw \"********\" {} {}\nSTDOUT: {}\nSTDERR: {}",
          (createAttributes == null) ? "" : createAttributes, principal, stdOut, result.getStderr());
      throw new KerberosOperationException(String.format("Failed to create service principal for %s\nSTDOUT: %s\nSTDERR: %s",
          principal, stdOut, result.getStderr()));
    }
  }

  /**
   * Removes an existing principal in a previously configured KDC
   * <p/>
   * The implementation is specific to a particular type of KDC.
   *
   * @param principal a String containing the principal to remove
   * @param service   a boolean value indicating whether the principal is for a service or not
   * @return true if the principal was successfully removed; otherwise false
   * @throws KerberosKDCConnectionException       if a connection to the KDC cannot be made
   * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
   * @throws KerberosRealmException               if the realm does not map to a KDC
   * @throws KerberosOperationException           if an unexpected error occurred
   */
  @Override
  public boolean removePrincipal(String principal, boolean service) throws KerberosOperationException {
    if (!isOpen()) {
      throw new KerberosOperationException("This operation handler has not been opened");
    }

    if (StringUtils.isEmpty(principal)) {
      throw new KerberosOperationException("Failed to remove principal - no principal specified");
    }

    ShellCommandUtil.Result result = invokeKAdmin(String.format("delete_principal -force %s", principal));

    // If there is data from STDOUT, see if the following string exists:
    //    Principal "<principal>" created
    String stdOut = result.getStdout();
    return (stdOut != null) && !stdOut.contains("Principal does not exist");
  }

  /**
   * Invokes the kadmin shell command to issue queries
   *
   * @param query a String containing the query to send to the kdamin command
   * @return a ShellCommandUtil.Result containing the result of the operation
   * @throws KerberosKDCConnectionException       if a connection to the KDC cannot be made
   * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
   * @throws KerberosRealmException               if the realm does not map to a KDC
   * @throws KerberosOperationException           if an unexpected error occurred
   */
  protected ShellCommandUtil.Result invokeKAdmin(String query)
      throws KerberosOperationException {
    if (StringUtils.isEmpty(query)) {
      throw new KerberosOperationException("Missing kadmin query");
    }

    if (StringUtils.isEmpty(executableKadmin)) {
      throw new KerberosOperationException("No path for kadmin is available - this KerberosOperationHandler may not have been opened.");
    }

    List<String> command = new ArrayList<>();
    command.add(executableKadmin);

    // Add the credential cache, if available
    String credentialCacheFilePath = getCredentialCacheFilePath();
    if (!StringUtils.isEmpty(credentialCacheFilePath)) {
      command.add("-c");
      command.add(credentialCacheFilePath);
    }

    // Add explicit KDC admin host, if available
    String adminSeverHost = getAdminServerHost();
    if (!StringUtils.isEmpty(adminSeverHost)) {
      command.add("-s");
      command.add(adminSeverHost);
    }

    // Add default realm clause, if available
    String defaultRealm = getDefaultRealm();
    if (!StringUtils.isEmpty(defaultRealm)) {
      command.add("-r");
      command.add(defaultRealm);
    }

    // Add kadmin query
    command.add("-q");
    command.add(query);

    if (LOG.isDebugEnabled()) {
      LOG.debug("Executing: {}", command);
    }

    ShellCommandUtil.Result result = null;
    int retryCount = configuration.getKerberosOperationRetries();
    int tries = 0;

    while (tries <= retryCount) {
      try {
        result = executeCommand(command.toArray(new String[command.size()]));
      } catch (KerberosOperationException exception) {
        if (tries == retryCount) {
          throw exception;
        }
      }

      if (result != null && result.isSuccessful()) {
        break; // break on successful result
      }
      tries++;

      try {
        Thread.sleep(1000 * configuration.getKerberosOperationRetryTimeout());
      } catch (InterruptedException ignored) {
      }

      String message = String.format("Retrying to execute kadmin after a wait of %d seconds :\n\tCommand: %s",
          configuration.getKerberosOperationRetryTimeout(),
          command);
      LOG.warn(message);
    }


    if ((result == null) || !result.isSuccessful()) {
      int exitCode = (result == null) ? -999 : result.getExitCode();
      String stdOut = (result == null) ? "" : result.getStdout();
      String stdErr = (result == null) ? "" : result.getStderr();

      String message = String.format("Failed to execute kadmin:\n\tCommand: %s\n\tExitCode: %s\n\tSTDOUT: %s\n\tSTDERR: %s",
          command, exitCode, stdOut, stdErr);
      LOG.warn(message);

      // Test STDERR to see of any "expected" error conditions were encountered...
      // Did admin credentials fail?
      if (stdErr.contains("Client not found in Kerberos database")) {
        throw new KerberosAdminAuthenticationException(stdErr);
      } else if (stdErr.contains("Incorrect password while initializing")) {
        throw new KerberosAdminAuthenticationException(stdErr);
      }
      // Did we fail to connect to the KDC?
      else if (stdErr.contains("Cannot contact any KDC")) {
        throw new KerberosKDCConnectionException(stdErr);
      } else if (stdErr.contains("Cannot resolve network address for admin server in requested realm while initializing kadmin interface")) {
        throw new KerberosKDCConnectionException(stdErr);
      }
      // Was the realm invalid?
      else if (stdErr.contains("Missing parameters in krb5.conf required for kadmin client")) {
        throw new KerberosRealmException(stdErr);
      } else if (stdErr.contains("Cannot find KDC for requested realm while initializing kadmin interface")) {
        throw new KerberosRealmException(stdErr);
      } else {
        throw new KerberosOperationException(String.format("Unexpected error condition executing the kadmin command. STDERR: %s", stdErr));
      }
    } else {
      if (LOG.isDebugEnabled()) {
        LOG.debug("Executed the following command:\n{}\nSTDOUT: {}\nSTDERR: {}",
            StringUtils.join(command, " "), result.getStdout(), result.getStderr());
      }
    }

    return result;
  }

  @Override
  protected String[] getKinitCommand(String executableKinit, PrincipalKeyCredential credentials, String credentialsCache) {
    // kinit -c <path> -S kadmin/`hostname -f` <principal>
    return new String[]{
        executableKinit,
        "-c",
        credentialsCache,
        "-S",
        String.format("kadmin/%s", getAdminServerHost()),
        credentials.getPrincipal()
    };
  }

  @Override
  protected void exportKeytabFile(String principal, String keytabFileDestinationPath, Set<EncryptionType> keyEncryptionTypes) throws KerberosOperationException {
    String encryptionTypeSpec = null;
    if (!CollectionUtils.isEmpty(keyEncryptionTypes)) {
      StringBuilder encryptionTypeSpecBuilder = new StringBuilder();
      for (EncryptionType encryptionType : keyEncryptionTypes) {
        if (encryptionTypeSpecBuilder.length() > 0) {
          encryptionTypeSpecBuilder.append(',');
        }
        encryptionTypeSpecBuilder.append(encryptionType.getName());
        encryptionTypeSpecBuilder.append(":normal");
      }

      encryptionTypeSpec = encryptionTypeSpecBuilder.toString();
    }

    String query = (StringUtils.isEmpty(encryptionTypeSpec))
        ? String.format("xst -k \"%s\" %s", keytabFileDestinationPath, principal)
        : String.format("xst -k \"%s\" -e %s %s", keytabFileDestinationPath, encryptionTypeSpec, principal);

    ShellCommandUtil.Result result = invokeKAdmin(query);

    if (!result.isSuccessful()) {
      String message = String.format("Failed to export the keytab file for %s:\n\tExitCode: %s\n\tSTDOUT: %s\n\tSTDERR: %s",
          principal, result.getExitCode(), result.getStdout(), result.getStderr());
      LOG.warn(message);
      throw new KerberosOperationException(message);
    }
  }
}
