/*
 * 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.server.rest.ssl;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.drill.common.config.DrillConfig;
import org.apache.drill.exec.ExecConstants;
import org.apache.drill.exec.ssl.SSLConfig;
import org.apache.drill.exec.ssl.SSLConfigBuilder;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Configures {@link SslContextFactory} when https is enabled for Web UI
 */
public class SslContextFactoryConfigurator {
  private static final Logger logger = LoggerFactory.getLogger(SslContextFactoryConfigurator.class);

  private final DrillConfig config;
  private final String drillbitEndpointAddress;

  public SslContextFactoryConfigurator(DrillConfig config, String drillbitEndpointAddress) {
    this.config = config;
    this.drillbitEndpointAddress = drillbitEndpointAddress;
  }

  /**
   * Tries to apply ssl options configured by user. If provided configuration isn't valid,
   * new self-signed certificate will be generated and used in sslContextFactory.
   *
   * @return new configured sslContextFactory
   * @throws Exception when generation of self-signed certificate failed
   */
  public SslContextFactory configureNewSslContextFactory() throws Exception {
    SSLConfig sslConf = new SSLConfigBuilder()
        .config(config)
        .mode(SSLConfig.Mode.SERVER)
        .initializeSSLContext(false)
        .validateKeyStore(true)
        .build();
    final SslContextFactory sslContextFactory = new SslContextFactory();
    if (sslConf.isSslValid()) {
      useOptionsConfiguredByUser(sslContextFactory, sslConf);
    } else {
      useAutoGeneratedSelfSignedCertificate(sslContextFactory);
    }
    return sslContextFactory;
  }

  private void useOptionsConfiguredByUser(SslContextFactory sslFactory, SSLConfig sslConf) {
    logger.info("Using configured SSL settings for web server");
    sslFactory.setKeyStorePath(sslConf.getKeyStorePath());
    sslFactory.setKeyStorePassword(sslConf.getKeyStorePassword());
    sslFactory.setKeyManagerPassword(sslConf.getKeyPassword());
    if (sslConf.hasTrustStorePath()) {
      sslFactory.setTrustStorePath(sslConf.getTrustStorePath());
      if (sslConf.hasTrustStorePassword()) {
        sslFactory.setTrustStorePassword(sslConf.getTrustStorePassword());
      }
    }
    sslFactory.setProtocol(sslConf.getProtocol());
    sslFactory.setIncludeProtocols(sslConf.getProtocol());
    logger.info("Web server configured to use TLS protocol '{}'", sslConf.getProtocol());
    if (config.hasPath(ExecConstants.HTTP_JETTY_SSL_CONTEXT_FACTORY_OPTIONS_PREFIX)) {
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_CERT_ALIAS, sslFactory::setCertAlias);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_CRL_PATH, sslFactory::setCrlPath);
      setBooleanIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_ENABLE_CRLDP, sslFactory::setEnableCRLDP);
      setBooleanIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_ENABLE_OCSP, sslFactory::setEnableOCSP);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_ENDPOINT_IDENTIFICATION_ALGORITHM, sslFactory::setEndpointIdentificationAlgorithm);
      setStringArrayIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_EXCLUDE_CIPHER_SUITES, sslFactory::setExcludeCipherSuites);
      setStringArrayIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_EXCLUDE_PROTOCOLS, sslFactory::setExcludeProtocols);
      setStringArrayIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_INCLUDE_CIPHER_SUITES, sslFactory::setIncludeCipherSuites);
      setStringArrayIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_INCLUDE_PROTOCOLS, sslFactory::setIncludeProtocols);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_KEY_MANAGER_FACTORY_ALGORITHM, sslFactory::setKeyManagerFactoryAlgorithm);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_KEYSTORE_PROVIDER, sslFactory::setKeyStoreProvider);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_KEYSTORE_TYPE, sslFactory::setKeyStoreType);
      setIntIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_MAX_CERT_PATH_LENGTH, sslFactory::setMaxCertPathLength);
      setBooleanIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_NEED_CLIENT_AUTH, sslFactory::setNeedClientAuth);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_OCSP_RESPONDER_URL, sslFactory::setOcspResponderURL);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_PROVIDER, sslFactory::setProvider);
      setBooleanIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_RENEGOTIATION_ALLOWED, sslFactory::setRenegotiationAllowed);
      setIntIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_RENEGOTIATION_LIMIT, sslFactory::setRenegotiationLimit);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_SECURE_RANDOM_ALGORITHM, sslFactory::setSecureRandomAlgorithm);
      setBooleanIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_SESSION_CACHING_ENABLED, sslFactory::setSessionCachingEnabled);
      setIntIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_SSL_SESSION_CACHE_SIZE, sslFactory::setSslSessionCacheSize);
      setIntIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_SSL_SESSION_TIMEOUT, sslFactory::setSslSessionTimeout);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_TRUSTMANAGERFACTORY_ALGORITHM, sslFactory::setTrustManagerFactoryAlgorithm);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_TRUSTSTORE_PROVIDER, sslFactory::setTrustStoreProvider);
      setStringIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_TRUSTSTORE_TYPE, sslFactory::setTrustStoreType);
      setBooleanIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_USE_CIPHER_SUITE_ORDER, sslFactory::setUseCipherSuitesOrder);
      setBooleanIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_VALIDATE_CERTS, sslFactory::setValidateCerts);
      setBooleanIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_VALIDATE_PEER_CERTS, sslFactory::setValidatePeerCerts);
      setBooleanIfPresent(ExecConstants.HTTP_JETTY_SERVER_SSL_CONTEXT_FACTORY_WANT_CLIENT_AUTH, sslFactory::setWantClientAuth);
    }
  }

  private void setStringArrayIfPresent(String optKey, Consumer<String[]> optSet) {
    setIfPresent(optKey,
        key -> {
          List<String> list = config.getStringList(key);
          return list == null ? null : list.toArray(new String[0]);
        },
        optSet);
  }

  private void setBooleanIfPresent(String optKey, Consumer<Boolean> optSet) {
    setIfPresent(optKey, config::getBoolean, optSet);
  }

  private void setStringIfPresent(String optKey, Consumer<String> optSet) {
    setIfPresent(optKey, config::getString, optSet);
  }

  private void setIntIfPresent(String optKey, Consumer<Integer> optSet) {
    setIfPresent(optKey, config::getInt, optSet);
  }

  private <T> void setIfPresent(String optKey, Function<String, T> optGet, Consumer<T> optSet) {
    if (config.hasPath(optKey)) {
      T optVal = optGet.apply(optKey);
      if (optVal != null) {
        optSet.accept(optVal);
      }
    }
  }


  private void useAutoGeneratedSelfSignedCertificate(SslContextFactory sslContextFactory) throws Exception {
    logger.info("Using generated self-signed SSL settings for web server");
    final SecureRandom random = new SecureRandom();

    // Generate a private-public key pair
    final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(1024, random);
    final KeyPair keyPair = keyPairGenerator.generateKeyPair();


    // Create builder for certificate attributes
    final X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE)
        .addRDN(BCStyle.OU, "Apache Drill (auth-generated)")
        .addRDN(BCStyle.O, "Apache Software Foundation (auto-generated)")
        .addRDN(BCStyle.CN, drillbitEndpointAddress);

    final DateTime now = DateTime.now();
    final Date notBefore = now.minusMinutes(1).toDate();
    final Date notAfter = now.plusYears(5).toDate();
    final BigInteger serialNumber = new BigInteger(128, random);

    // Create a certificate valid for 5years from now.
    final X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder(
        nameBuilder.build(), // attributes
        serialNumber,
        notBefore,
        notAfter,
        nameBuilder.build(),
        keyPair.getPublic());

    // Sign the certificate using the private key
    final ContentSigner contentSigner =
        new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(keyPair.getPrivate());
    final X509Certificate certificate =
        new JcaX509CertificateConverter().getCertificate(certificateBuilder.build(contentSigner));

    // Check the validity
    certificate.checkValidity(now.toDate());

    // Make sure the certificate is self-signed.
    certificate.verify(certificate.getPublicKey());

    // Generate a random password for keystore protection
    final String keyStorePasswd = RandomStringUtils.random(20);
    final KeyStore keyStore = KeyStore.getInstance("JKS");
    keyStore.load(null, null);
    keyStore.setKeyEntry("DrillAutoGeneratedCert", keyPair.getPrivate(),
        keyStorePasswd.toCharArray(), new java.security.cert.Certificate[]{certificate});

    sslContextFactory.setKeyStore(keyStore);
    sslContextFactory.setKeyStorePassword(keyStorePasswd);
  }
}
