/*
 * 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.ranger.server.tomcat;

import java.io.File;
import java.io.IOException;
import java.security.PrivilegedAction;
import java.util.Date;
import java.util.Iterator;
import java.util.Properties;
import java.util.logging.Logger;
import java.util.List;
import javax.servlet.ServletException;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.hadoop.security.SecureClientLogin;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.alias.CredentialProvider;
import org.apache.hadoop.security.alias.CredentialProviderFactory;
import org.apache.hadoop.security.alias.JavaKeyStoreProvider;
import org.apache.ranger.plugin.util.XMLUtils;
import javax.security.auth.Subject;

public class EmbeddedServer {
	
	private static final Logger LOG = Logger.getLogger(EmbeddedServer.class
			.getName());
	private static final String DEFAULT_NAME_RULE = "DEFAULT";
	
	private static final String DEFAULT_CONFIG_FILENAME = "ranger-admin-default-site.xml";
	private static final String CORE_SITE_CONFIG_FILENAME = "core-site.xml";
	
	private static final String DEFAULT_WEBAPPS_ROOT_FOLDER = "webapps";
	
	private static String configFile = "ranger-admin-site.xml";
	
	private static final String AUTH_TYPE_KERBEROS = "kerberos";
    private static final String AUTHENTICATION_TYPE = "hadoop.security.authentication";
    private static final String ADMIN_USER_PRINCIPAL = "ranger.admin.kerberos.principal";
    private static final String ADMIN_USER_KEYTAB = "ranger.admin.kerberos.keytab";

	private static final String ADMIN_NAME_RULES = "hadoop.security.auth_to_local";
	private static final String ADMIN_SERVER_NAME = "rangeradmin";
	
	private Properties serverConfigProperties = new Properties();

	public static void main(String[] args) {
		new EmbeddedServer(args).start();
	}
	
	public EmbeddedServer(String[] args) {
		if (args.length > 0) {
			configFile = args[0];
		} else {
			XMLUtils.loadConfig(DEFAULT_CONFIG_FILENAME, serverConfigProperties);
		}
		XMLUtils.loadConfig(CORE_SITE_CONFIG_FILENAME, serverConfigProperties);
        XMLUtils.loadConfig(configFile, serverConfigProperties);
	}
	
	public static int DEFAULT_SHUTDOWN_PORT = 6185;
	public static String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN";
	
	public void start() {
		final Tomcat server = new Tomcat();

		String logDir =  null;
		logDir = getConfig("logdir");
		if (logDir == null) {
			logDir = getConfig("kms.log.dir");
		}
		String servername = getConfig("servername");
		String hostName = getConfig("ranger.service.host");
		int serverPort = getIntConfig("ranger.service.http.port", 6181);
		int sslPort = getIntConfig("ranger.service.https.port", -1);
		int shutdownPort = getIntConfig("ranger.service.shutdown.port",DEFAULT_SHUTDOWN_PORT);
		String shutdownCommand = getConfig("ranger.service.shutdown.command",DEFAULT_SHUTDOWN_COMMAND);

		server.setHostname(hostName);
		server.setPort(serverPort);
		server.getServer().setPort(shutdownPort);
		server.getServer().setShutdown(shutdownCommand);

		boolean isHttpsEnabled = Boolean.valueOf(getConfig("ranger.service.https.attrib.ssl.enabled", "false"));
		boolean ajpEnabled = Boolean.valueOf(getConfig("ajp.enabled", "false"));

		if (ajpEnabled) {

			Connector ajpConnector = new Connector(
					"org.apache.coyote.ajp.AjpNioProtocol");
			ajpConnector.setPort(serverPort);
			ajpConnector.setProperty("protocol", "AJP/1.3");

			server.getService().addConnector(ajpConnector);

			// Making this as a default connector
			server.setConnector(ajpConnector);
			LOG.info("Created AJP Connector");
		} else if ((sslPort > 0) && isHttpsEnabled) {
			Connector ssl = new Connector();
			ssl.setPort(sslPort);
			ssl.setSecure(true);
			ssl.setScheme("https");
			ssl.setAttribute("SSLEnabled", "true");
			ssl.setAttribute("sslProtocol", getConfig("ranger.service.https.attrib.ssl.protocol", "TLS"));
			String clientAuth=getConfig("ranger.service.https.attrib.clientAuth", "false");
			if("false".equalsIgnoreCase(clientAuth)){
				clientAuth=getConfig("ranger.service.https.attrib.client.auth", "want");
			}
			ssl.setAttribute("clientAuth",clientAuth);
			String providerPath=getConfig("ranger.credential.provider.path");
			String keyAlias= getConfig("ranger.service.https.attrib.keystore.credential.alias","keyStoreCredentialAlias");
			String keystorePass=null;
			if(providerPath!=null && keyAlias!=null){
				keystorePass=getDecryptedString(providerPath.trim(), keyAlias.trim());
				if(keystorePass==null || keystorePass.trim().isEmpty() || "none".equalsIgnoreCase(keystorePass.trim())){
					keystorePass=getConfig("ranger.service.https.attrib.keystore.pass");
				}
			}
			ssl.setAttribute("keyAlias", getConfig("ranger.service.https.attrib.keystore.keyalias","rangeradmin"));
			ssl.setAttribute("keystorePass", keystorePass);
			ssl.setAttribute("keystoreFile", getKeystoreFile());
			
                        String defaultEnabledProtocols = "SSLv2Hello, TLSv1, TLSv1.1, TLSv1.2";
                        String enabledProtocols = getConfig("ranger.service.https.attrib.ssl.enabled.protocols", defaultEnabledProtocols);
			ssl.setAttribute("sslEnabledProtocols", enabledProtocols);
			String ciphers = getConfig("ranger.tomcat.ciphers");
			if (ciphers != null && ciphers.trim() != null && ciphers.trim().length() > 0) {
				ssl.setAttribute("ciphers", ciphers);
			}
			server.getService().addConnector(ssl);

			//
			// Making this as a default connector
			//
			server.setConnector(ssl);
			
		}
		updateHttpConnectorAttribConfig(server);
		
		File logDirectory = new File(logDir);
		if (!logDirectory.exists()) {
			logDirectory.mkdirs();
		}
		
		AccessLogValve valve = new AccessLogValve();
		valve.setRotatable(true);
		valve.setAsyncSupported(true);
		valve.setBuffered(false);
		valve.setEnabled(true);
		valve.setFileDateFormat(getConfig("ranger.accesslog.dateformat", "yyyy-MM-dd.HH"));
		valve.setDirectory(logDirectory.getAbsolutePath());
		valve.setSuffix(".log");
		
		String logPattern = getConfig("ranger.accesslog.pattern", "%h %l %u %t \"%r\" %s %b");
		valve.setPattern(logPattern);	
				
		server.getHost().getPipeline().addValve(valve);
		
		try {
			String webapp_dir = getConfig("xa.webapp.dir");
			if (webapp_dir == null || webapp_dir.trim().isEmpty()) {
				// If webapp location property is not set, then let's derive
				// from catalina_base
				String catalina_base = getConfig("catalina.base");
				if (catalina_base == null || catalina_base.trim().isEmpty()) {
					LOG.severe("Tomcat Server failed to start: catalina.base and/or xa.webapp.dir is not set");
					System.exit(1);
				}
				webapp_dir = catalina_base + File.separator + "webapp";
				LOG.info("Deriving webapp folder from catalina.base property. folder="
						+ webapp_dir);
			}
			
			//String webContextName = getConfig("xa.webapp.contextName", "/");
			String webContextName = getConfig("ranger.contextName", "/");
			if (webContextName == null) {
				webContextName = "/";
			} else if (!webContextName.startsWith("/")) {
				LOG.info("Context Name [" + webContextName
						+ "] is being loaded as [ /" + webContextName + "]");
				webContextName = "/" + webContextName;
			}
			
			File wad = new File(webapp_dir);
			if (wad.isDirectory()) {
				LOG.info("Webapp file =" + webapp_dir + ", webAppName = "
						+ webContextName);
			} else if (wad.isFile()) {
				File webAppDir = new File(DEFAULT_WEBAPPS_ROOT_FOLDER);
				if (!webAppDir.exists()) {
					webAppDir.mkdirs();
				}
				LOG.info("Webapp file =" + webapp_dir + ", webAppName = "
						+ webContextName);
			}
			LOG.info("Adding webapp [" + webContextName + "] = path ["
					+ webapp_dir + "] .....");
			Context webappCtx = server.addWebapp(webContextName, new File(
					webapp_dir).getAbsolutePath());
			webappCtx.init();
			LOG.info("Finished init of webapp [" + webContextName
					+ "] = path [" + webapp_dir + "].");
		} catch (ServletException e1) {
			LOG.severe("Tomcat Server failed to add webapp:" + e1.toString());
			e1.printStackTrace();
		} catch (LifecycleException lce) {
			LOG.severe("Tomcat Server failed to start webapp:" + lce.toString());
			lce.printStackTrace();
		}
		
		if (servername.equalsIgnoreCase(ADMIN_SERVER_NAME)) {
			String keytab = getConfig(ADMIN_USER_KEYTAB);
			String principal = null;
			try {
				principal = SecureClientLogin.getPrincipal(getConfig(ADMIN_USER_PRINCIPAL), hostName);
			} catch (IOException ignored) {
				LOG.warning("Failed to get ranger.admin.kerberos.principal. Reason: " + ignored.toString());
			}
			String nameRules = getConfig(ADMIN_NAME_RULES);
			if (nameRules == null || nameRules.length() == 0) {
				LOG.info("Name is empty. Setting Name Rule as 'DEFAULT'");
				nameRules = DEFAULT_NAME_RULE;
			}
			if (getConfig(AUTHENTICATION_TYPE) != null
					&& getConfig(AUTHENTICATION_TYPE).trim().equalsIgnoreCase(AUTH_TYPE_KERBEROS)
					&& SecureClientLogin.isKerberosCredentialExists(principal,keytab)) {
				try{
					LOG.info("Provided Kerberos Credential : Principal = "
							+ principal + " and Keytab = " + keytab);
					Subject sub = SecureClientLogin.loginUserFromKeytab(principal, keytab, nameRules);
					Subject.doAs(sub, new PrivilegedAction<Void>() {
						@Override
						public Void run() {
							LOG.info("Starting Server using kerberos credential");
							startServer(server);
							return null;
						}
					});
				} catch (Exception e) {
					LOG.severe("Tomcat Server failed to start:" + e.toString());
					e.printStackTrace();
				}
			} else {
				startServer(server);
			}
		} else {
			startServer(server);
		}
	}

	private void startServer(final Tomcat server) {
		try {
			server.start();
			server.getServer().await();
			shutdownServer();
		} catch (LifecycleException e) {
			LOG.severe("Tomcat Server failed to start:" + e.toString());
			e.printStackTrace();
		} catch (Exception e) {
			LOG.severe("Tomcat Server failed to start:" + e.toString());
			e.printStackTrace();
		}
	}

	private String getKeystoreFile() {
		String keystoreFile=getConfig("ranger.service.https.attrib.keystore.file");
		if (keystoreFile == null || keystoreFile.trim().isEmpty()) {
			// new property not configured, lets use the old property
			keystoreFile = getConfig("ranger.https.attrib.keystore.file");
		}
		return keystoreFile;
	}

	protected String getConfig(String key) {
		String value = serverConfigProperties.getProperty(key);
		if (value == null || value.trim().isEmpty()) {
			// Value not found in properties file, let's try to get from
			// System's property
			value = System.getProperty(key);
		}
		return value;
	}
	
	protected String getConfig(String key, String defaultValue) {
		String ret = getConfig(key);
		if (ret == null) {
			ret = defaultValue;
		}
		return ret;
	}
	
	protected int getIntConfig(String key, int defaultValue) {
		int ret = defaultValue;
		String retStr = getConfig(key);
		try {
			if (retStr != null) {
				ret = Integer.parseInt(retStr);
			}
		} catch (Exception err) {
			LOG.warning(retStr + " can't be parsed to int. Reason: " + err.toString());
		}
		return ret;
	}
	
	public void shutdownServer() {
		int timeWaitForShutdownInSeconds = getIntConfig(
				"service.waitTimeForForceShutdownInSeconds", 0);
		if (timeWaitForShutdownInSeconds > 0) {
			long endTime = System.currentTimeMillis()
					+ (timeWaitForShutdownInSeconds * 1000L);
			LOG.info("Will wait for all threads to shutdown gracefully. Final shutdown Time: "
					+ new Date(endTime));
			while (System.currentTimeMillis() < endTime) {
				int activeCount = Thread.activeCount();
				if (activeCount == 0) {
				    LOG.info("Number of active threads = " + activeCount + ".");
					break;
				} else {
					LOG.info("Number of active threads = " + activeCount
							+ ". Waiting for all threads to shutdown ...");
					try {
						Thread.sleep(5000L);
					} catch (InterruptedException e) {
						LOG.warning("shutdownServer process is interrupted with exception: "
								+ e);
						break;
					}
				}
			}
		}
		LOG.info("Shuting down the Server.");
		System.exit(0);
	}

	protected long getLongConfig(String key, long defaultValue) {
		long ret = defaultValue;
		String retStr = getConfig(key);
		try{
			if (retStr != null) {
		        ret = Long.parseLong(retStr);
			}
		}catch(Exception err){
			LOG.warning(retStr + " can't be parsed to long. Reason: " + err.toString());
		}
		return ret;
	}
	public void updateHttpConnectorAttribConfig(Tomcat server) {
		server.getConnector().setAllowTrace(Boolean.valueOf(getConfig("ranger.service.http.connector.attrib.allowTrace","false")));
		server.getConnector().setAsyncTimeout(getLongConfig("ranger.service.http.connector.attrib.asyncTimeout", 10000));
		server.getConnector().setEnableLookups(Boolean.valueOf(getConfig("ranger.service.http.connector.attrib.enableLookups","false")));
		server.getConnector().setMaxHeaderCount(getIntConfig("ranger.service.http.connector.attrib.maxHeaderCount", 100));
		server.getConnector().setMaxParameterCount(getIntConfig("ranger.service.http.connector.attrib.maxParameterCount", 10000));
		server.getConnector().setMaxPostSize(getIntConfig("ranger.service.http.connector.attrib.maxPostSize", 2097152));
		server.getConnector().setMaxSavePostSize(getIntConfig("ranger.service.http.connector.attrib.maxSavePostSize", 4096));
		server.getConnector().setParseBodyMethods(getConfig("ranger.service.http.connector.attrib.methods", "POST"));
		server.getConnector().setURIEncoding(getConfig("ranger.service.http.connector.attrib.URIEncoding", "UTF-8"));
		Iterator<Object> iterator = serverConfigProperties.keySet().iterator();
		String key = null;
		String property = null;
		while (iterator.hasNext()){
			key = iterator.next().toString();
			if(key != null && key.startsWith("ranger.service.http.connector.property.")){
				property = key.replace("ranger.service.http.connector.property.","");
				server.getConnector().setProperty(property,getConfig(key));
				LOG.info(property + ":" + server.getConnector().getProperty(property));
			}
		}
	}

	public String getDecryptedString(String CrendentialProviderPath,String alias) {
		String credential=null;
		try{
			if(CrendentialProviderPath==null || alias==null||CrendentialProviderPath.trim().isEmpty()||alias.trim().isEmpty()){
				return null;
			}
			char[] pass = null;
			Configuration conf = new Configuration();
			String crendentialProviderPrefixJceks=JavaKeyStoreProvider.SCHEME_NAME + "://file";
			String crendentialProviderPrefixLocalJceks="localjceks://file";
			crendentialProviderPrefixJceks=crendentialProviderPrefixJceks.toLowerCase();
			CrendentialProviderPath=CrendentialProviderPath.trim();
			alias=alias.trim();
			if(CrendentialProviderPath.toLowerCase().startsWith(crendentialProviderPrefixJceks) ||  CrendentialProviderPath.toLowerCase().startsWith(crendentialProviderPrefixLocalJceks)){
				conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH,CrendentialProviderPath);
			}else{
				if(CrendentialProviderPath.startsWith("/")){
					conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH,JavaKeyStoreProvider.SCHEME_NAME + "://file" + CrendentialProviderPath);
				}else{
					conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH,JavaKeyStoreProvider.SCHEME_NAME + "://file/" + CrendentialProviderPath);
				}
			}
			List<CredentialProvider> providers = CredentialProviderFactory.getProviders(conf);
			List<String> aliasesList;
			CredentialProvider.CredentialEntry credEntry=null;
			for(CredentialProvider provider: providers) {
				//System.out.println("Credential Provider :" + provider);
				aliasesList=provider.getAliases();
				if(aliasesList!=null && aliasesList.contains(alias.toLowerCase())){
					credEntry=null;
					credEntry= provider.getCredentialEntry(alias);
					pass = credEntry.getCredential();
					if(pass!=null && pass.length>0){
						credential=String.valueOf(pass);
						break;
					}
				}
			}
		}catch(Exception ex){
			LOG.severe("CredentialReader failed while decrypting provided string. Reason: " + ex.toString());
			credential=null;
		}
		return credential;
	}
}
