Package org.glite.authz.pap.ui.cli

Source Code of org.glite.authz.pap.ui.cli.ServiceCLI

/**
* Copyright (c) Members of the EGEE Collaboration. 2006-2009.
* See http://www.eu-egee.org/partners/ for details on the copyright holders.
*
* 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 org.glite.authz.pap.ui.cli;

import java.io.File;
import java.io.FileInputStream;
import java.io.PrintWriter;
import java.rmi.RemoteException;
import java.util.Collection;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.glite.authz.pap.client.ServiceClient;
import org.glite.authz.pap.client.ServiceClientFactory;
import org.glite.authz.pap.common.Pap;
import org.glite.authz.pap.common.exceptions.PAPException;
import org.glite.authz.pap.common.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.emi.security.authn.x509.impl.PEMCredential;

public abstract class ServiceCLI {

    public static enum ExitStatus {
        // Attention keep that order because elements ordinal number is used.
        SUCCESS, // value = 0
        PARTIAL_SUCCESS, // value = 1
        FAILURE, // value = 2
        INITIALIZATION_ERROR, // value = 3
        PARSE_ERROR, // value = 4
        REMOTE_EXCEPTION
        // value = 5
    }

    private static final Logger log = LoggerFactory.getLogger(ServiceCLI.class);

    private static final HelpFormatter helpFormatter = new HelpFormatter();

    private static final String OPT_PROXY_DESCRIPTION = "Specifies a user proxy to be used for authentication.";
    private static final String OPT_PROXY_LONG = "proxy";

    private static final String OPT_CERT_DESCRIPTION = "Specifies non-standard user certificate.";
    private static final String OPT_CERT_LONG = "cert";

    private static final String OPT_HOST_DESCRIPTION = "Specifies the target PAP hostname (default is localhost). "
            + "This option defines the PAP endpoint to be contacted as follows: https://arg:port"
            + Pap.DEFAULT_SERVICES_ROOT_PATH;
    private static final String OPT_HOST_LONG = "host";

    private static final String OPT_KEY_DESCRIPTION = "Specifies non-standard user private key.";
    private static final String OPT_KEY_LONG = "key";

    private static final String OPT_PORT = "p";
    private static final String OPT_PORT_DESCRIPTION = "Specifies the port on which the target PAP is listening "
            + "(default is " + Pap.DEFAULT_PORT + ")";
    private static final String OPT_PORT_LONG = "port";

    private static final String OPT_URL_LONG = "url";

    private static final String OPT_VERBOSE = "v";
    private static final String OPT_VERBOSE_DESCRIPTION = "Verbose mode.";
    private static final String OPT_VERBOSE_LONG = "verbose";

    protected static final String DEFAULT_SERVICE_URL = "https://%s:%s%s";

    protected static final String OPT_HELP = "h";
    protected static final String OPT_HELP_DESCRIPTION = "Print this message.";
    protected static final String OPT_HELP_LONG = "help";

    protected static final String OPT_PRIVATE_LONG = "private";
    protected static final String OPT_PUBLIC_LONG = "public";

    protected static final String PAP_HOST_PROPERTY = "host";
    protected static final String PAP_PORT_PROPERTY = "port";
   
    protected static final CommandLineParser parser = new GnuParser();
    private String[] commandNameValues;
    private Options commandOptions;
    private String descriptionText;
    private static Options globalOptions;
    private String longDescriptionText;
    private Options options;
    private final ServiceClient serviceClient;
    private String usageText;
    protected boolean verboseMode = false;

    static {
        globalOptions = defineGlobalOptions();
    }

    @SuppressWarnings("unchecked")
    public ServiceCLI(String[] commandNameValues, String usage, String description, String longDescription) {

        ServiceClientFactory serviceClientFactory = ServiceClientFactory.getServiceClientFactory();
        serviceClient = serviceClientFactory.createServiceClient();

        helpFormatter.setWidth(80);
        helpFormatter.setLeftPadding(4);

        this.commandNameValues = commandNameValues;
        this.usageText = usage;
        this.descriptionText = description;
        this.longDescriptionText = longDescription;

        commandOptions = defineCommandOptions();
        if (commandOptions == null)
            commandOptions = new Options();

        commandOptions.addOption(OPT_HELP, OPT_HELP_LONG, false, OPT_HELP_DESCRIPTION);

        options = new Options();
        Collection<Option> optionsList = commandOptions.getOptions();
        for (Option opt : optionsList) {
            options.addOption(opt);
        }

        optionsList = globalOptions.getOptions();
        for (Option opt : optionsList) {
            options.addOption(opt);
        }
    }

    public static Options getGlobalOptions() {
        return globalOptions;
    }

    @SuppressWarnings("static-access")
    private static Options defineGlobalOptions() {

        Options options = new Options();

        // TODO: OPT_URL and (OPT_HOST, OPT_PORT) are mutually exclusive
        // options. Use OptionGroup.
        options.addOption(OptionBuilder.hasArg(true)
                                       .withLongOpt(OPT_URL_LONG)
                                       .withDescription("Specifies the target PAP endpoint (default: "
                                               + String.format(DEFAULT_SERVICE_URL,
                                                               Pap.DEFAULT_HOST,
                                                               Pap.DEFAULT_PORT,
                                                               Pap.DEFAULT_SERVICES_ROOT_PATH) + ").")
                                       .withArgName("url")
                                       .create());
        options.addOption(OptionBuilder.hasArg(true)
                                       .withLongOpt(OPT_HOST_LONG)
                                       .withDescription(OPT_HOST_DESCRIPTION)
                                       .withArgName("hostname")
                                       .create());
        options.addOption(OptionBuilder.hasArg(true)
                                       .withLongOpt(OPT_PORT_LONG)
                                       .withDescription(OPT_PORT_DESCRIPTION)
                                       .create(OPT_PORT));
        options.addOption(OptionBuilder.hasArg(true)
                                       .withLongOpt(OPT_PROXY_LONG)
                                       .withDescription(OPT_PROXY_DESCRIPTION)
                                       .withArgName("file")
                                       .create());
        options.addOption(OptionBuilder.hasArg(true)
                                       .withLongOpt(OPT_CERT_LONG)
                                       .withDescription(OPT_CERT_DESCRIPTION)
                                       .withArgName("file")
                                       .create());
        options.addOption(OptionBuilder.hasArg(true)
                                       .withLongOpt(OPT_KEY_LONG)
                                       .withDescription(OPT_KEY_DESCRIPTION)
                                       .withArgName("file")
                                       .create());
        options.addOption(OptionBuilder.hasArg(false)
                                       .withLongOpt(OPT_VERBOSE_LONG)
                                       .withDescription(OPT_VERBOSE_DESCRIPTION)
                                       .create(OPT_VERBOSE));
        return options;
    }

    public boolean commandMatch(String command) {
        for (String value : commandNameValues) {
            if (value.equals(command))
                return true;
        }
        return false;
    }

   
    public int execute(String[] args) throws ParseException, HelpMessageException, RemoteException {

        CommandLine commandLine = parser.parse(options, args);

        if (commandLine.hasOption(OPT_HELP)) {
            throw new HelpMessageException();
        }

        if (commandLine.hasOption(OPT_VERBOSE)) {
            verboseMode = true;
        }

        if (commandLine.hasOption(OPT_URL_LONG)) {

            serviceClient.setTargetEndpoint(commandLine.getOptionValue(OPT_URL_LONG));

        } else {

            String host = Pap.DEFAULT_HOST;
           
           
           
            String papHostProperty = System.getProperty(PAP_HOST_PROPERTY);
           
            if (papHostProperty != null && !"".equals(papHostProperty.trim())){
              host = papHostProperty;
            }
           
            String port = Pap.DEFAULT_PORT;
           
            String papPortProperty = System.getProperty(PAP_PORT_PROPERTY);
            if (papPortProperty != null && !"".equals(papPortProperty.trim())){
          port = papPortProperty;
            }

            if (commandLine.hasOption(OPT_HOST_LONG)) {
                host = commandLine.getOptionValue(OPT_HOST_LONG);
            }

            if (commandLine.hasOption(OPT_PORT)) {
                port = commandLine.getOptionValue(OPT_PORT);
            }
           
            try {
                Integer.valueOf(port);
            } catch (NumberFormatException e) {
                throw new ParseException(String.format("Invalid port number \"%s\" (option -%s, --%s)",
                                                       port,
                                                       OPT_PORT,
                                                       OPT_PORT_LONG));
            }

            serviceClient.setTargetEndpoint(String.format(DEFAULT_SERVICE_URL,
                                                          host,
                                                          port,
                                                          Pap.DEFAULT_SERVICES_ROOT_PATH));

        }

        boolean credentialsNotRetrieved = true;

        if (commandLine.hasOption(OPT_PROXY_LONG)) {
            serviceClient.setClientProxy(commandLine.getOptionValue(OPT_PROXY_LONG));
            credentialsNotRetrieved = false;
        }

        if (commandLine.hasOption(OPT_CERT_LONG)) {
            if (commandLine.hasOption(OPT_PROXY_LONG)) {
                throw new ParseException(String.format("Conflicting options --%s and --%s.",
                                                       OPT_PROXY_LONG,
                                                       OPT_CERT_LONG));
            } else {
                if (!commandLine.hasOption(OPT_KEY_LONG)) {
                    throw new ParseException(String.format("Option --%s requires also option --%s.",
                                                           OPT_CERT_LONG,
                                                           OPT_KEY_LONG));
                }
                serviceClient.setClientCertificate(commandLine.getOptionValue(OPT_CERT_LONG));
                credentialsNotRetrieved = false;
            }
        }

        if (commandLine.hasOption(OPT_KEY_LONG)) {
            if (commandLine.hasOption(OPT_PROXY_LONG)) {
                throw new ParseException(String.format("Conflicting options --%s and --%s.",
                                                       OPT_PROXY_LONG,
                                                       OPT_KEY_LONG));
            } else {
                if (!commandLine.hasOption(OPT_CERT_LONG)) {
                    throw new ParseException(String.format("Option --%s requires also option --%s.",
                                                           OPT_KEY_LONG,
                                                           OPT_CERT_LONG));
                }
                serviceClient.setClientPrivateKey(commandLine.getOptionValue(OPT_KEY_LONG));
                credentialsNotRetrieved = false;
            }
        }

        if (credentialsNotRetrieved) {

            // 1. if running as root take the cert /etc/grid-security/hostcert.pem
            // 2. check the env variable X509_USER_PROXY
            // 3. check the env variable X509_USER_CERT (and X509_USER_KEY)
            // 4. check the proxy /tmp/x509up_u<id_utente>
            // 5. check the cert $HOME/.globus/usercert.pem and key $HOME/.globus/userkey.pem

            String euid = getEUID();

            if (euid == null) {

                log.error("Cannot enstabilish user's effective user id.");

                throw new PAPException(String.format("Cannot enstabilish user's effective user id, please use the --%s or --%s, --%s options.",
                                                     OPT_PROXY_LONG,
                                                     OPT_CERT_LONG,
                                                     OPT_KEY_LONG));
            }

            String messageString = null;

            if ("0".equals(euid)) {
                // user: root

                if (setCertFromEnvironment()) {

                    messageString = String.format("Connecting to %s using %s and %s (from environment X509_USER_CERT and X509_USER_KEY)",
                                                  serviceClient.getTargetEndpoint(),
                                                  serviceClient.getClientCertificate(),
                                                  serviceClient.getClientPrivateKey());

                } else {

                    serviceClient.setClientCertificate("/etc/grid-security/hostcert.pem");
                    serviceClient.setClientPrivateKey("/etc/grid-security/hostkey.pem");

                    messageString = String.format("Connecting to %s using %s and %s",
                                                  serviceClient.getTargetEndpoint(),
                                                  serviceClient.getClientCertificate(),
                                                  serviceClient.getClientPrivateKey());
                }
            } else {

                if (setProxyFromEnvironment()) {

                    messageString = String.format("Connecting to %s using proxy (from environment X509_USER_PROXY)  %s",
                                                  serviceClient.getTargetEndpoint(),
                                                  serviceClient.getClientProxy());

                } else if (setCertFromEnvironment()) {

                    messageString = String.format("Connecting to %s using %s and %s (from environment X509_USER_CERT and X509_USER_KEY)",
                                                  serviceClient.getTargetEndpoint(),
                                                  serviceClient.getClientCertificate(),
                                                  serviceClient.getClientPrivateKey());

                } else if (setProxyFromStandardLocation(euid)) {
                    messageString = String.format("Connecting to %s using proxy %s",
                                                  serviceClient.getTargetEndpoint(),
                                                  serviceClient.getClientProxy());

                } else if (setCertFromHomeDir()) {

                    messageString = String.format("Connecting to %s using %s and %s",
                                                  serviceClient.getTargetEndpoint(),
                                                  serviceClient.getClientCertificate(),
                                                  serviceClient.getClientPrivateKey());

                } else {
                    throw new ParseException(String.format("Unable to find a certificate or a proxy, please specify a proxy file with option --%s or certificate and key with options --%s and --%s",
                                                           OPT_PROXY_LONG,
                                                           OPT_CERT_LONG,
                                                           OPT_KEY_LONG));
                }

            }

            log.info(messageString);

            if (verboseMode) {
                System.out.println(messageString);
            }
        }

       
        if (serviceClient.getClientPrivateKey() != null) {
         
          String keyPassword = getPrivateKeyPasswordFromConsole(serviceClient.getClientPrivateKey(),
              serviceClient.getClientCertificate());
         
          if (keyPassword != null)
            serviceClient.setClientPrivateKeyPassword(keyPassword);
         
        }

        return executeCommandService(commandLine, serviceClient);
    }

    private String getPrivateKeyPasswordFromConsole(String keyFile, String certFile){
      String prompt = "Please enter the passphrase for the private key file " + keyFile
                + ": ";
     
      ConsolePasswordFinder pf = new ConsolePasswordFinder(prompt);
     
      try {
     
        new PEMCredential(new FileInputStream(keyFile),
          new FileInputStream(certFile), pf);
     
    } catch (Exception e) {
      log.error(e.getMessage(),e);
      throw new PAPException(e.getMessage(),e);
    }
     
      return pf.getLastReadPassword();
    }
   
   
    public String[] getCommandNameValues() {
        return commandNameValues;
    }

    public ServiceClient getServiceClient() {
        return serviceClient;
    }

    public void printHelpMessage(PrintWriter pw) {
        String syntax = String.format("pap-admin [global-options] %s %s", commandNameValues[0], usageText);

        pw.println();
        helpFormatter.printUsage(pw, helpFormatter.getWidth(), syntax);

        if (descriptionText != null) {
            pw.println();
            helpFormatter.printWrapped(pw, helpFormatter.getWidth(), descriptionText);
        }

        if (longDescriptionText != null) {
            pw.println();
            helpFormatter.printWrapped(pw, helpFormatter.getWidth(), longDescriptionText);
        }

        // command specific options
        pw.println();
        helpFormatter.printWrapped(pw, helpFormatter.getWidth(), "Valid options:");
        helpFormatter.printOptions(pw,
                                   helpFormatter.getWidth(),
                                   commandOptions,
                                   helpFormatter.getLeftPadding(),
                                   helpFormatter.getDescPadding());

        // global options
        pw.println();
        helpFormatter.printWrapped(pw, helpFormatter.getWidth(), "Global options:");
        helpFormatter.printOptions(pw,
                                   helpFormatter.getWidth(),
                                   globalOptions,
                                   helpFormatter.getLeftPadding(),
                                   helpFormatter.getDescPadding());
    }

    protected abstract Options defineCommandOptions();

    protected abstract int executeCommandService(CommandLine commandLine, ServiceClient serviceClient)
            throws CLIException, ParseException, RemoteException;

    protected void printErrorMessage(String msg) {
        System.out.println(msg);
    }

    protected void printOutputMessage(String msg) {
        System.out.println(msg);
    }

    protected void printVerboseMessage(String msg) {
        if (verboseMode)
            System.out.println(msg);
    }

    /**
     * Return the effective user ID.
     *
     * @return the effective user ID or <code>null</code> if the effective user ID couldn't be established.
     */
    private String getEUID() {

        String euid = System.getenv("EUID");

        if (!Utils.isDefined(euid)) {
            String euidProperty = System.getProperty("effectiveUserId");

            if (Utils.isDefined(euidProperty)) {
                euid = euidProperty;
            } else {
                euid = null;
            }
        }

        return euid;
    }

    /**
     * Set the certificate and the key in {@link ServiceCLI#serviceClient} using ~/.globus/user{cert,key}.pem.
     *
     * @return <code>true</code> if cert and key were found, <code>false</code> otherwise.
     *
     */
    private boolean setCertFromHomeDir() throws ParseException {

        String baseDir = System.getProperty("user.home") + File.separator + ".globus" + File.separator;

        String cert = baseDir + "usercert.pem";
        String key = baseDir + "userkey.pem";

        File file = new File(cert);

        if (!file.exists()) {
            return false;
        }

        file = new File(key);

        if (!file.exists()) {
            return false;
        }

        serviceClient.setClientCertificate(cert);
        serviceClient.setClientPrivateKey(key);

        return true;
    }

    /**
     * Set the certificate the the key in {@link ServiceCLI#serviceClient} using the envirinment variables
     * X509_USER_CERT and X509_USER_KEY.
     *
     * @return <code>true</code> if the env variables are set, <code>false</code> otherwise.
     * @throws ParseException if only one of X509_USER_CERT or X509_USER_KEY is set.
     *
     */
    private boolean setCertFromEnvironment() throws ParseException {
        String x509UserCert = System.getenv("X509_USER_CERT");
        String x509UserKey = System.getenv("X509_USER_KEY");

        if (!Utils.isDefined(x509UserCert) && (!Utils.isDefined(x509UserKey))) {
            return false;
        }

        if (!(Utils.isDefined(x509UserCert) && Utils.isDefined(x509UserKey))) {
            if (Utils.isDefined(x509UserCert)) {
                throw new ParseException("Trying to use environment variable X509_USER_CERT for certificate but environment variable X509_USER_KEY is not set.");
            }
            throw new ParseException("Trying to use environment variable X509_USER_KEY for private key but environment variable X509_USER_CERT is not set.");
        }

        serviceClient.setClientCertificate(x509UserCert);
        serviceClient.setClientPrivateKey(x509UserKey);

        return true;
    }

    /**
     * Set the proxy in {@link ServiceCLI#serviceClient} using the location defined in the environment
     * variable X509_USER_PROXY.
     *
     * @return <code>true</code> if the env variable is set, <code>false</code> otherwise.
     */
    private boolean setProxyFromEnvironment() {

        String x509UserProxy = System.getenv("X509_USER_PROXY");

        if (Utils.isDefined(x509UserProxy)) {

            serviceClient.setClientProxy(x509UserProxy);
            return true;

        } else {
            return false;
        }
    }

    /**
     * Set the proxy in {@link ServiceCLI#serviceClient} using the standard location (i.e. /tmp).
     *
     * @param euid the effective user ID to build the proxy file name.
     * @return <code>true</code> the proxy was found, <code>false</code> otherwise.
     */
    private boolean setProxyFromStandardLocation(String euid) {

        String proxy = "/tmp/x509up_u" + euid;

        File file = new File(proxy);

        if (!file.exists()) {
            return false;
        }

        serviceClient.setClientProxy(proxy);

        return true;
    }
   
}
TOP

Related Classes of org.glite.authz.pap.ui.cli.ServiceCLI

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.