Package com.dtolabs.rundeck

Source Code of com.dtolabs.rundeck.RunServer

/*
* Copyright 2010 DTO Labs, Inc. (http://dtolabs.com)
*
* Licensed 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 com.dtolabs.rundeck;

import org.eclipse.jetty.plus.jaas.JAASLoginService;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.server.Handler;
import java.io.*;
import java.util.Properties;

/**
* Run the jetty server using system properties and commandline input for configuration
*/
public class RunServer {

    public static final String SERVER_HTTP_HOST = "server.http.host";
    public static final String RUNDECK_JETTY_CONNECTOR_FORWARDED = "rundeck.jetty.connector.forwarded";
    public static final String RUNDECK_JETTY_SSL_CONNECTOR_EXCLUDED_PROTOCOLS= "rundeck.jetty.connector.ssl.excludedProtocols";

    public static final String DEFAULT_SSL_CONNECTER_EXCLUDED_PROTOCOLS = "SSLv3";


    int port = Integer.getInteger("server.http.port", 4440);
    int httpsPort = Integer.getInteger("server.https.port", 4443);
    File basedir;
    File serverdir;
    private static final String REALM_NAME = "rundeckrealm";
    private static final String SYS_PROP_LOGIN_MODULE = "loginmodule.name";
    private static final String SYS_PROP_ROLE_CLASS_NAMES = "loginmodule.role.classnames";
    public static final String SYS_PROP_WEB_CONTEXT = "server.web.context";
    File configdir;
    String loginmodulename;
    String roleclassnames;
    private boolean useJaas;
    private static final String RUNDECK_JAASLOGIN = "rundeck.jaaslogin";
    public static final String RUNDECK_SSL_CONFIG = "rundeck.ssl.config";
    public static final String RUNDECK_KEYSTORE = "keystore";
    public static final String RUNDECK_KEYSTORE_PASSWORD = "keystore.password";
    public static final String RUNDECK_KEY_PASSWORD = "key.password";
    public static final String RUNDECK_TRUSTSTORE = "truststore";
    public static final String RUNDECK_TRUSTSTORE_PASSWORD = "truststore.password";
    private String keystore;
    private String keystorePassword;
    private String keyPassword;
    private String truststore;
    private String truststorePassword;
    private String appContext;
    private static final String RUNDECK_SERVER_SERVER_DIR = "rundeck.server.serverDir";
    private static final String RUNDECK_SERVER_CONFIG_DIR = "rundeck.server.configDir";

    public static void main(final String[] args) throws Exception {
        new RunServer().run(args);
    }

    public RunServer() {
        useJaas = null == System.getProperty(RUNDECK_JAASLOGIN) || Boolean.getBoolean(RUNDECK_JAASLOGIN);
        loginmodulename = System.getProperty(SYS_PROP_LOGIN_MODULE, "rundecklogin");
        roleclassnames = System.getProperty(SYS_PROP_ROLE_CLASS_NAMES, null);
        appContext = System.getProperty(SYS_PROP_WEB_CONTEXT, "/");
    }

    /**
     * Run with arguments
     *
     * @param args
     *
     * @throws Exception
     */
    public void run(final String[] args) throws Exception {
        parseArgs(args);
        init();
        if (null != basedir) {
            System.setProperty("rdeck.base", basedir.getAbsolutePath());
        }
        final Server server = new Server();
        if(isSSLEnabled()){
            configureSSLConnector(server);
        }else{
            warnNoSSLConfig();
            configureHTTPConnector(server);
        }

        server.setStopAtShutdown(true);
        final WebAppContext context = createWebAppContext(new File(serverdir, "exp/webapp"));

        server.setHandler(context);
        //context.getSessionHandler().getSessionManager().setHttpOnly(true);//TODO: upgrade jetty to support HttpOnly session cookies

        configureRealms(server);
        try {
           
            server.start();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(100);
        }
    }

    private void warnNoSSLConfig() {
        System.err.println("WARNING: HTTPS is not enabled, specify -Drundeck.ssl.config="+(basedir.getAbsolutePath().replaceAll("\\\\","/"))+"/server/config/ssl.properties to enable.");
    }

    private boolean isSSLEnabled() {
        if (null == System.getProperty(RUNDECK_SSL_CONFIG)) {
            return false;
        }
        if (null != keystore) {
            if (!new File(keystore).exists()) {
                System.err.println("ERROR: keystore file does not exist, you must create it: " + keystore);
                return false;
            }
        } else {
            System.err.println("ERROR: keystore property not specified: " + System.getProperty(RUNDECK_SSL_CONFIG));
            return false;
        }
        return true;
    }

    private void configureHTTPConnector(final Server server) {
        final SelectChannelConnector connector = new SelectChannelConnector();
        connector.setPort(port);
        connector.setHost(System.getProperty(SERVER_HTTP_HOST, null));
        connector.setForwarded(Boolean.getBoolean(RUNDECK_JETTY_CONNECTOR_FORWARDED));
        server.addConnector(connector);
    }

    private void configureSSLConnector(final Server server) {
        //configure ssl
        final SslSelectChannelConnector connector = new SslSelectChannelConnector();
        connector.setPort(httpsPort);
        connector.setMaxIdleTime(30000);
        connector.setForwarded(Boolean.getBoolean(RUNDECK_JETTY_CONNECTOR_FORWARDED));
        SslContextFactory cf = connector.getSslContextFactory();
        cf.setKeyStorePath(keystore);
        cf.setKeyStorePassword(keystorePassword);
        cf.setKeyManagerPassword(keyPassword);
        cf.setTrustStore(truststore);
        cf.setTrustStorePassword(truststorePassword);
        cf.setExcludeProtocols(
                System.getProperty(
                        RUNDECK_JETTY_SSL_CONNECTOR_EXCLUDED_PROTOCOLS,
                        DEFAULT_SSL_CONNECTER_EXCLUDED_PROTOCOLS
                ).split(",")
        );
        connector.setHost(System.getProperty(SERVER_HTTP_HOST, null));
        server.addConnector(connector);
    }

    /**
     * Configure jetty realm.  if system property "rundeck.jaaslogin" is false, then use a simple HashRealm, otherwise
     * use a JAAS realm.
     *
     * @param server
     *
     * @throws IOException
     */
    private void configureRealms(final Server server) throws IOException {
        if (useJaas) {
            configureJAASRealms(server);
        } else {
            configureHashRealms(server);
        }
    }

    /**
     * Configure HashUserRealm for realm.properties in the config dir
     *
     * @param server
     *
     * @throws IOException
     */
    private void configureHashRealms(final Server server) throws IOException {
        HashLoginService realm = new HashLoginService();
        realm.setName(REALM_NAME);
        final File conffile = new File(configdir, "realm.properties");
        realm.setConfig(conffile.getAbsolutePath());
        server.addBean(realm);
    }

    /**
     * Configure JAAS realm using login module name "rundecklogin"
     *
     * @param server
     */
    private void configureJAASRealms(final Server server) {
        final JAASLoginService realm = new JAASLoginService();
        realm.setName(REALM_NAME);
        realm.setLoginModuleName(loginmodulename);

        if (null != roleclassnames && !"".equals(roleclassnames.trim())) {
            final String[] strings = roleclassnames.split(",\\s*");
            realm.setRoleClassNames(strings);
        }

        server.addBean(realm);
    }

    /**
     * Create the webapp context for the given path
     *
     * @param webapp webapp path
     *
     * @return
     *
     * @throws IOException
     */
    private WebAppContext createWebAppContext(final File webapp) throws IOException {
        if (!webapp.isDirectory() || !new File(webapp, "WEB-INF").isDirectory()) {
            throw new RuntimeException("expected expanded webapp at location: " + webapp.getAbsolutePath());
        }
        final WebAppContext context = new WebAppContext(webapp.getAbsolutePath(), appContext);
        context.setTempDirectory(new File(serverdir, "work"));
        context.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
        return context;
    }

    /**
     * init values based on provided system properties or arguments. System property "rundeck.server.serverDir" sets the
     * server location, defaults to basedir/server. "rundeck.server.configDir" sets the config dir location, defaults to
     * serverdir/config
     */
    private void init() {
        if (null != System.getProperty(RUNDECK_SERVER_SERVER_DIR)) {
            serverdir = new File(System.getProperty(RUNDECK_SERVER_SERVER_DIR));
        } else {
            serverdir = new File(basedir, "server");
        }
        if (null != System.getProperty(RUNDECK_SERVER_CONFIG_DIR)) {
            configdir = new File(System.getProperty(RUNDECK_SERVER_CONFIG_DIR));
        } else {
            configdir = new File(serverdir, "config");
        }
        if(null!=System.getProperty(RUNDECK_SSL_CONFIG)){
            final Properties sslProperties = new Properties();
            try{
                sslProperties.load(new FileInputStream(System.getProperty(RUNDECK_SSL_CONFIG)));
            } catch (IOException e) {
                System.err.println("Could not load specified rundeck.ssl.config file: " + System.getProperty(
                    RUNDECK_SSL_CONFIG) + ": " + e.getMessage());
                e.printStackTrace(System.err);
            }
            keystore = sslProperties.getProperty(RUNDECK_KEYSTORE);
            keystorePassword = sslProperties.getProperty(RUNDECK_KEYSTORE_PASSWORD);
            keyPassword = sslProperties.getProperty(RUNDECK_KEY_PASSWORD);
            truststore = sslProperties.getProperty(RUNDECK_TRUSTSTORE);
            truststorePassword = sslProperties.getProperty(RUNDECK_TRUSTSTORE_PASSWORD);
        }
    }

    /**
     * Parse CLI arguments as input options.  current usage: <basedir> [port]
     *
     * @param args
     */
    private void parseArgs(final String[] args) {
        if (args.length > 0) {
            basedir = new File(args[0]);
        } else {
            throw new RuntimeException("Basedir argument required");
        }
        if (args.length > 1) {
            port = Integer.parseInt(args[1]);
        }
        if (args.length > 2) {
            httpsPort = Integer.parseInt(args[2]);
        }
    }
}
TOP

Related Classes of com.dtolabs.rundeck.RunServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.