/*
 * 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.knox.gateway.services.security.impl;

import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.security.auth.x500.X500Principal;

import org.apache.knox.gateway.GatewayMessages;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.services.ServiceLifecycleException;
import org.apache.knox.gateway.services.security.AliasService;
import org.apache.knox.gateway.services.security.AliasServiceException;
import org.apache.knox.gateway.services.security.KeystoreService;
import org.apache.knox.gateway.services.security.KeystoreServiceException;
import org.apache.knox.gateway.services.security.SSLService;
import org.apache.knox.gateway.util.X500PrincipalParser;
import org.eclipse.jetty.util.ssl.SslContextFactory;

public class JettySSLService implements SSLService {
  private static final String EPHEMERAL_DH_KEY_SIZE_PROPERTY = "jdk.tls.ephemeralDHKeySize";
  private static final String GATEWAY_CREDENTIAL_STORE_NAME = "__gateway";
  private static GatewayMessages log = MessagesFactory.get( GatewayMessages.class );

  private KeystoreService keystoreService;
  private AliasService aliasService;

  public void setAliasService(AliasService as) {
    this.aliasService = as;
  }

  public void setKeystoreService(KeystoreService ks) {
    this.keystoreService = ks;
  }

  @Override
  public void init(GatewayConfig config, Map<String, String> options)
      throws ServiceLifecycleException {
    // set any JSSE or security related system properties
    System.setProperty(EPHEMERAL_DH_KEY_SIZE_PROPERTY, config.getEphemeralDHKeySize());
    try {
      if (!keystoreService.isCredentialStoreForClusterAvailable(GATEWAY_CREDENTIAL_STORE_NAME)) {
        log.creatingCredentialStoreForGateway();
        keystoreService.createCredentialStoreForCluster(GATEWAY_CREDENTIAL_STORE_NAME);
        // LET'S NOT GENERATE A DIFFERENT KEY PASSPHRASE BY DEFAULT ANYMORE
        // IF A DEPLOYMENT WANTS TO CHANGE THE KEY PASSPHRASE TO MAKE IT MORE SECURE THEN
        // THEY CAN ADD THE ALIAS EXPLICITLY WITH THE CLI
        // as.generateAliasForCluster(GATEWAY_CREDENTIAL_STORE_NAME, GATEWAY_IDENTITY_PASSPHRASE);
      }
      else {
        log.credentialStoreForGatewayFoundNotCreating();
      }
    } catch (KeystoreServiceException e) {
      throw new ServiceLifecycleException("Keystore was not loaded properly - the provided password may not match the password for the keystore.", e);
    }

    try {
      if (!keystoreService.isKeystoreForGatewayAvailable()) {
        log.creatingKeyStoreForGateway();
        keystoreService.createKeystoreForGateway();
        char[] passphrase;
        try {
          passphrase = aliasService.getGatewayIdentityPassphrase();
        } catch (AliasServiceException e) {
          throw new ServiceLifecycleException("Error accessing credential store for the gateway.", e);
        }
        keystoreService.addSelfSignedCertForGateway(config.getIdentityKeyAlias(), passphrase);
      }
      else {
        log.keyStoreForGatewayFoundNotCreating();
      }
      logAndValidateCertificate(config);
    } catch (KeystoreServiceException e) {
      throw new ServiceLifecycleException("The identity keystore was not loaded properly - the provided password may not match the password for the keystore.", e);
    }
  }

  private void logAndValidateCertificate(GatewayConfig config) throws ServiceLifecycleException {
    // let's log the hostname (CN) and cert expiry from the gateway's public cert to aid in SSL debugging
    Certificate cert;
    final String identityKeyAlias = config.getIdentityKeyAlias();
    try {
      cert = aliasService.getCertificateForGateway(identityKeyAlias);
    } catch (AliasServiceException e) {
      throw new ServiceLifecycleException("Cannot Retreive Gateway SSL Certificate. Server will not start.", e);
    }
    if (cert != null) {
      if (cert instanceof X509Certificate) {
        X500Principal x500Principal = ((X509Certificate)cert).getSubjectX500Principal();
        X500PrincipalParser parser = new X500PrincipalParser(x500Principal);
        log.certificateHostNameForGateway(parser.getCN());
        Date notBefore = ((X509Certificate) cert).getNotBefore();
        Date notAfter = ((X509Certificate) cert).getNotAfter();
        log.certificateValidityPeriod(notBefore, notAfter);

        // let's not even start if the current date is not within the validity period for the SSL cert
        try {
          ((X509Certificate)cert).checkValidity();
        } catch (CertificateExpiredException e) {
          throw new ServiceLifecycleException("Gateway SSL Certificate is Expired. Server will not start.", e);
        } catch (CertificateNotYetValidException e) {
          throw new ServiceLifecycleException("Gateway SSL Certificate is not yet valid. Server will not start.", e);
        }
      } else {
        throw new ServiceLifecycleException("Public certificate for the gateway is not of the expected type of  . Something is wrong with the gateway keystore.");
      }
    } else {
      throw new ServiceLifecycleException("Public certificate for the gateway cannot be found with the alias " + identityKeyAlias + ". Please check the identity certificate alias.");
    }
  }

  @Override
  public Object buildSslContextFactory(GatewayConfig config) throws AliasServiceException {
    String identityKeystorePath = config.getIdentityKeystorePath();
    String identityKeystoreType = config.getIdentityKeystoreType();
    String identityKeyAlias = config.getIdentityKeyAlias();

    SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
    sslContextFactory.setCertAlias( identityKeyAlias );
    sslContextFactory.setKeyStoreType(identityKeystoreType);
    sslContextFactory.setKeyStorePath(identityKeystorePath );

    char[] keystorePasswordChars;
    try {
      keystorePasswordChars = aliasService.getGatewayIdentityKeystorePassword();
    } catch (AliasServiceException e) {
      log.failedToGetPasswordForGatewayIdentityKeystore(e);
      throw e;
    }
    if(keystorePasswordChars != null) {
      sslContextFactory.setKeyStorePassword(new String(keystorePasswordChars));
    }

    char[] keypass;
    try {
      keypass = aliasService.getGatewayIdentityPassphrase();
    } catch (AliasServiceException e) {
      log.failedToGetPassphraseForGatewayIdentityKey(e);
      throw e;
    }
    if(keypass != null) {
      sslContextFactory.setKeyManagerPassword(new String(keypass));
    }

    boolean clientAuthNeeded = config.isClientAuthNeeded();
    boolean clientAuthWanted = config.isClientAuthWanted();
    if (clientAuthNeeded || clientAuthWanted) {
      String truststorePath = config.getTruststorePath();
      String trustStoreType;
      char[] truststorePassword;

      if (truststorePath != null) {
        String trustStorePasswordAlias = config.getTruststorePasswordAlias();
        trustStoreType = config.getTruststoreType();

        try {
          truststorePassword = aliasService.getPasswordFromAliasForGateway(trustStorePasswordAlias);
        } catch (AliasServiceException e) {
          log.failedToGetPasswordForGatewayTruststore(trustStorePasswordAlias, e);
          throw e;
        }
      }
      else {
        // when clientAuthIsNeeded but no truststore provided
        // default to the server's keystore and details
        truststorePath = identityKeystorePath;
        trustStoreType = identityKeystoreType;

        try {
          truststorePassword = aliasService.getGatewayIdentityKeystorePassword();
        } catch (AliasServiceException e) {
          log.failedToGetPasswordForGatewayTruststore(config.getIdentityKeystorePasswordAlias(), e);
          throw e;
        }
      }

      sslContextFactory.setTrustStorePath(truststorePath);
      if(truststorePassword != null) {
        sslContextFactory.setTrustStorePassword(new String(truststorePassword));
      }
      sslContextFactory.setTrustStoreType(trustStoreType);
    }
    if (clientAuthNeeded) {
      sslContextFactory.setNeedClientAuth( clientAuthNeeded );
    }
    else {
      sslContextFactory.setWantClientAuth( clientAuthWanted );
    }

    sslContextFactory.setTrustAll( config.getTrustAllCerts() );

    List<String> sslIncludeCiphers = config.getIncludedSSLCiphers();
    if (sslIncludeCiphers != null && !sslIncludeCiphers.isEmpty()) {
      sslContextFactory.setIncludeCipherSuites( sslIncludeCiphers.toArray(new String[0]) );
    }

    List<String> sslExcludeCiphers = config.getExcludedSSLCiphers();
    if (sslExcludeCiphers != null && !sslExcludeCiphers.isEmpty()) {
      sslContextFactory.setExcludeCipherSuites( sslExcludeCiphers.toArray(new String[0]) );
    }

    List<String> sslExcludeProtocols = config.getExcludedSSLProtocols();
    if (sslExcludeProtocols != null && !sslExcludeProtocols.isEmpty()) {
      sslContextFactory.setExcludeProtocols( sslExcludeProtocols.toArray(new String[0]) );
    }

    sslContextFactory.setRenegotiationAllowed(config.isSSLRenegotiationAllowed());
    return sslContextFactory;
  }

  @Override
  public void start() throws ServiceLifecycleException {
  }

  @Override
  public void stop() throws ServiceLifecycleException {
  }
}
