/*
 * 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.drill.exec.ssl;

import com.google.common.base.Preconditions;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import org.apache.drill.common.config.DrillConfig;
import org.apache.drill.common.exceptions.DrillException;
import org.apache.drill.exec.ExecConstants;
import org.apache.drill.exec.memory.BufferAllocator;
import org.apache.hadoop.conf.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;

public class SSLConfigServer extends SSLConfig {

  private static final Logger logger = LoggerFactory.getLogger(SSLConfigServer.class);

  private final DrillConfig config;
  private final Configuration hadoopConfig;
  private final boolean userSslEnabled;
  private final boolean httpsEnabled;
  private final String keyStoreType;
  private final String keyStorePath;
  private final String keyStorePassword;
  private final String keyPassword;
  private final String trustStoreType;
  private final String trustStorePath;
  private final String trustStorePassword;
  private final String protocol;
  private final String provider;

  public SSLConfigServer(DrillConfig config, Configuration hadoopConfig) throws DrillException {
    this.config = config;
    Mode mode = Mode.SERVER;
    httpsEnabled =
        config.hasPath(ExecConstants.HTTP_ENABLE_SSL) && config.getBoolean(ExecConstants.HTTP_ENABLE_SSL);
    // For testing we will mock up a hadoop configuration, however for regular use, we find the actual hadoop config.
    boolean enableHadoopConfig = config.getBoolean(ExecConstants.SSL_USE_HADOOP_CONF);
    if (enableHadoopConfig) {
      if (hadoopConfig == null) {
        this.hadoopConfig = new Configuration(); // get hadoop configuration
      } else {
        this.hadoopConfig = hadoopConfig;
      }
      String hadoopSSLConfigFile =
          this.hadoopConfig.get(resolveHadoopPropertyName(HADOOP_SSL_CONF_TPL_KEY, getMode()));
      logger.debug("Using Hadoop configuration for SSL");
      logger.debug("Hadoop SSL configuration file: {}", hadoopSSLConfigFile);
      this.hadoopConfig.addResource(hadoopSSLConfigFile);
    } else {
      this.hadoopConfig = null;
    }
    userSslEnabled =
        config.hasPath(ExecConstants.USER_SSL_ENABLED) && config.getBoolean(ExecConstants.USER_SSL_ENABLED);
    SSLCredentialsProvider credentialsProvider = SSLCredentialsProvider.getSSLCredentialsProvider(
        this::getConfigParam,
        this::getPasswordConfigParam,
        Mode.SERVER
    );
    trustStoreType = credentialsProvider.getTrustStoreType(
        ExecConstants.SSL_TRUSTSTORE_TYPE, resolveHadoopPropertyName(HADOOP_SSL_TRUSTSTORE_TYPE_TPL_KEY, mode));
    trustStorePath = credentialsProvider.getTrustStoreLocation(
        ExecConstants.SSL_TRUSTSTORE_PATH, resolveHadoopPropertyName(HADOOP_SSL_TRUSTSTORE_LOCATION_TPL_KEY, mode));
    trustStorePassword = credentialsProvider.getTrustStorePassword(
        ExecConstants.SSL_TRUSTSTORE_PASSWORD, resolveHadoopPropertyName(HADOOP_SSL_TRUSTSTORE_PASSWORD_TPL_KEY, mode));
    keyStoreType = credentialsProvider.getKeyStoreType(
        ExecConstants.SSL_KEYSTORE_TYPE, resolveHadoopPropertyName(HADOOP_SSL_KEYSTORE_TYPE_TPL_KEY, mode));
    keyStorePath = credentialsProvider.getKeyStoreLocation(
        ExecConstants.SSL_KEYSTORE_PATH, resolveHadoopPropertyName(HADOOP_SSL_KEYSTORE_LOCATION_TPL_KEY, mode));
    keyStorePassword = credentialsProvider.getKeyStorePassword(
        ExecConstants.SSL_KEYSTORE_PASSWORD, resolveHadoopPropertyName(HADOOP_SSL_KEYSTORE_PASSWORD_TPL_KEY, mode));
    String keyPass = credentialsProvider.getKeyPassword(
        ExecConstants.SSL_KEY_PASSWORD, resolveHadoopPropertyName(HADOOP_SSL_KEYSTORE_KEYPASSWORD_TPL_KEY, mode));
    // if no keypassword specified, use keystore password
    keyPassword = keyPass.isEmpty() ? keyStorePassword : keyPass;
    protocol = config.getString(ExecConstants.SSL_PROTOCOL);
    // If provider is OPENSSL then to debug or run this code in an IDE, you will need to enable
    // the dependency on netty-tcnative with the correct classifier for the platform you use.
    // This can be done by enabling the openssl profile.
    // If the IDE is Eclipse, it requires you to install an additional Eclipse plugin available here:
    // http://repo1.maven.org/maven2/kr/motd/maven/os-maven-plugin/1.6.1/os-maven-plugin-1.6.1.jar
    // or from your local maven repository:
    // ~/.m2/repository/kr/motd/maven/os-maven-plugin/1.6.1/os-maven-plugin-1.6.1.jar
    // Note that installing this plugin may require you to start with a new workspace
    provider = config.getString(ExecConstants.SSL_PROVIDER);
  }

  @Override
  public void validateKeyStore() throws DrillException {
    //HTTPS validates the keystore is not empty. User Server SSL context initialization also validates keystore, but
    // much more strictly. User Client context initialization does not validate keystore.
    /*If keystorePath or keystorePassword is provided in the configuration file use that*/
    if ((isUserSslEnabled() || isHttpsEnabled())) {
      if (!keyStorePath.isEmpty() || !keyStorePassword.isEmpty()) {
        if (keyStorePath.isEmpty()) {
          throw new DrillException(
              " *.ssl.keyStorePath in the configuration file is empty, but *.ssl.keyStorePassword is set");
        } else if (keyStorePassword.isEmpty()) {
          throw new DrillException(
              " *.ssl.keyStorePassword in the configuration file is empty, but *.ssl.keyStorePath is set ");
        }
      }
    }
  }

  @Override
  public SslContext initNettySslContext() throws DrillException {
    final SslContext sslCtx;

    if (!userSslEnabled) {
      return null;
    }

    KeyManagerFactory kmf;
    TrustManagerFactory tmf;
    try {
      if (keyStorePath.isEmpty()) {
        throw new DrillException("No Keystore provided.");
      }
      kmf = initializeKeyManagerFactory();
      tmf = initializeTrustManagerFactory();
      sslCtx = SslContextBuilder.forServer(kmf)
          .trustManager(tmf)
          .protocols(protocol)
          .sslProvider(getProvider())
          .build(); // Will throw an exception if the key password is not correct
    } catch (Exception e) {
      // Catch any SSL initialization Exceptions here and abort.
      throw new DrillException(new StringBuilder()
          .append("SSL is enabled but cannot be initialized - ")
          .append("[ ")
          .append(e.getMessage())
          .append("]. ")
          .toString());
    }
    this.nettySslContext = sslCtx;
    return sslCtx;
  }

  @Override
  public SSLContext initJDKSSLContext() throws DrillException {
    final SSLContext sslCtx;

    if (!userSslEnabled) {
      return null;
    }

    KeyManagerFactory kmf;
    TrustManagerFactory tmf;
    try {
      if (keyStorePath.isEmpty()) {
        throw new DrillException("No Keystore provided.");
      }
      kmf = initializeKeyManagerFactory();
      tmf = initializeTrustManagerFactory();
      sslCtx = SSLContext.getInstance(protocol);
      sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    } catch (Exception e) {
      // Catch any SSL initialization Exceptions here and abort.
      throw new DrillException(
          new StringBuilder().append("SSL is enabled but cannot be initialized - ")
              .append("[ ")
              .append(e.getMessage())
              .append("]. ")
              .toString());
    }
    this.jdkSSlContext = sslCtx;
    return sslCtx;
  }

  @Override
  public SSLEngine createSSLEngine(BufferAllocator allocator, String peerHost, int peerPort) {
    SSLEngine engine = super.createSSLEngine(allocator, peerHost, peerPort);

    engine.setUseClientMode(false);

    // No need for client side authentication (HTTPS like behaviour)
    engine.setNeedClientAuth(false);

    try {
      engine.setEnableSessionCreation(true);
    } catch (Exception e) {
      // Openssl implementation may throw this.
      logger.debug("Session creation not enabled. Exception: {}", e.getMessage());
    }

    return engine;
  }

  private String getConfigParam(String name, String hadoopName) {
    String value = "";
    if (hadoopConfig != null) {
      value = getHadoopConfigParam(hadoopName);
    }
    if (value.isEmpty() && config.hasPath(name)) {
      value = config.getString(name);
    }
    value = value.trim();
    return value;
  }

  private String getHadoopConfigParam(String name) {
    Preconditions.checkArgument(this.hadoopConfig != null);
    String value = hadoopConfig.get(name, "");
    value = value.trim();
    return value;
  }

  private String getPasswordConfigParam(String name, String hadoopName) {
    String value = getPassword(hadoopName);

    if (value == null) {
      value = getConfigParam(name, hadoopName);
    }

    return value;
  }

  @Override
  public boolean isUserSslEnabled() {
    return userSslEnabled;
  }

  @Override
  public boolean isHttpsEnabled() {
    return httpsEnabled;
  }

  @Override
  public String getKeyStoreType() {
    return keyStoreType;
  }

  @Override
  public String getKeyStorePath() {
    return keyStorePath;
  }

  @Override
  public String getKeyStorePassword() {
    return keyStorePassword;
  }

  @Override
  public String getKeyPassword() {
    return keyPassword;
  }

  @Override
  public String getTrustStoreType() {
    return trustStoreType;
  }

  @Override
  public boolean hasTrustStorePath() {
    return !trustStorePath.isEmpty();
  }

  @Override
  public String getTrustStorePath() {
    return trustStorePath;
  }

  @Override
  public boolean hasTrustStorePassword() {
    return !trustStorePassword.isEmpty();
  }

  @Override
  public String getTrustStorePassword() {
    return trustStorePassword;
  }

  @Override
  public String getProtocol() {
    return protocol;
  }

  @Override
  public SslProvider getProvider() {
    return provider.equalsIgnoreCase("JDK") ? SslProvider.JDK : SslProvider.OPENSSL;
  }

  @Override
  public int getHandshakeTimeout() {
    // A value of 0 is interpreted by Netty as "no timeout". This is hard coded
    // here instead being read from {@link ExecConstants.SSL_HANDSHAKE_TIMEOUT}
    // because the SSL handshake timeout is managed from the client end only
    // (see {@link SSLConfigClient}).
    return 0;
  }

  @Override
  public Mode getMode() {
    return Mode.SERVER;
  }

  @Override
  public boolean disableHostVerification() {
    return false;
  }

  @Override
  public boolean disableCertificateVerification() {
    return false;
  }

  @Override
  public boolean useSystemTrustStore() {
    return false; // Client only, notsupported by the server
  }

  @Override
  public boolean isSslValid() {
    return !keyStorePath.isEmpty() && !keyStorePassword.isEmpty();
  }

  @Override
  Configuration getHadoopConfig() {
    return hadoopConfig;
  }
}
