Package com.sun.enterprise.admin.cli.cluster

Source Code of com.sun.enterprise.admin.cli.cluster.NativeRemoteCommandsBase

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.admin.cli.cluster;

import com.sun.enterprise.util.io.FileUtils;
import java.io.*;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;

import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.ServiceLocatorFactory;
import org.glassfish.hk2.bootstrap.HK2Populator;
import org.glassfish.hk2.bootstrap.impl.ClasspathDescriptorFileFinder;
import org.glassfish.internal.api.Globals;
import org.glassfish.internal.api.RelativePathResolver;
import org.glassfish.api.Param;
import org.glassfish.api.admin.*;
import com.sun.enterprise.admin.cli.CLICommand;
import org.glassfish.cluster.ssh.launcher.SSHLauncher;
import org.glassfish.cluster.ssh.sftp.SFTPClient;

import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Nodes;
import com.sun.enterprise.config.serverbeans.Node;

import com.sun.enterprise.universal.glassfish.TokenResolver;
import com.sun.enterprise.util.io.DomainDirs;
import com.sun.enterprise.util.SystemPropertyConstants;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.util.net.NetUtils;

import com.trilead.ssh2.SFTPv3DirectoryEntry;

import org.jvnet.hk2.config.ConfigParser;
import org.jvnet.hk2.config.Dom;
import org.jvnet.hk2.config.DomDocument;

import com.sun.enterprise.security.store.PasswordAdapter;

/**
*  Base class for SSH provisioning commands.
*
*  Byron Nevins Aug 2011.  SSH was hard-coded in.  Now we
*  want to use jcifs (SAMBA) for Windows.
*/
abstract class NativeRemoteCommandsBase extends CLICommand {
    @Param(optional = false, primary = true, multiple = true)
    String[] hosts;
    String sshpassword;
    String sshkeypassphrase = null;
    boolean promptPass = false;
    TokenResolver resolver = null;
    private String remoteUser;
    private int remotePort;

    NativeRemoteCommandsBase() {
        // Create a resolver that can replace system properties in strings
        resolver = new TokenResolver();
    }

    // all of this rigamarole is to get the right names for parameters in front
    // of user eyeballs
    abstract String getRawRemoteUser();
    abstract int getRawRemotePort();
    abstract String getSshKeyFile();

    @Override
    protected void validate() throws CommandException {
        remoteUser = resolver.resolve(getRawRemoteUser());
    }

    final String getRemoteUser() {
        return remoteUser;
    }
    final int getRemotePort() {
        return remotePort;
    }
    final void setRemotePort(int newPort) {
        remotePort = newPort;
    }

    /**
     * Get SSH password from password file or user.
     */
    String getSSHPassword(String node) throws CommandException {
        return getRemotePassword(node, "AS_ADMIN_SSHPASSWORD");
    }

    /**
     * Get DCOM password from password file or user.
     */
    String getWindowsPassword(String node) throws CommandException {
        return getRemotePassword(node, "AS_ADMIN_WINDOWSPASSWORD");
    }

    /**
     * Get SSH password from password file or user.
     */
    private String getRemotePassword(String node, String key) throws CommandException {
        String password = getFromPasswordFile(key);

        if (password != null) {
            String alias = RelativePathResolver.getAlias(password);
            if (alias != null)
                password = expandPasswordAlias(node, alias, true);
        }

        //get password from user if not found in password file
        if (password == null) {
            if (programOpts.isInteractive()) {
                password = readPassword(Strings.get("SSHPasswordPrompt", getRemoteUser(), node));
            }
            else {
                throw new CommandException(Strings.get("SSHPasswordNotFound"));
            }
        }
        return password;
    }

    /**
     * Get SSH key passphrase from password file or user.
     */
    String getSSHPassphrase(boolean verifyConn) throws CommandException {
        String passphrase = getFromPasswordFile("AS_ADMIN_SSHKEYPASSPHRASE");

        if (passphrase != null) {
            String alias = RelativePathResolver.getAlias(passphrase);

            if (alias != null)
                passphrase = expandPasswordAlias(null, alias, verifyConn);
        }

        //get password from user if not found in password file
        if (passphrase == null) {
            if (programOpts.isInteractive()) {
                //i18n
                passphrase = readPassword(Strings.get("SSHPassphrasePrompt", getSshKeyFile()));
            }
            else {
                passphrase = ""; //empty passphrase
            }
        }
        return passphrase;
    }

    /**
     * Get domain master password from password file or user.
     */
    String getMasterPassword(String domain) throws CommandException {
        String masterPass = getFromPasswordFile("AS_ADMIN_MASTERPASSWORD");

        //get password from user if not found in password file
        if (masterPass == null) {
            if (programOpts.isInteractive()) {
                //i18n
                masterPass = readPassword(Strings.get("DomainMasterPasswordPrompt", domain));
            }
            else {
                masterPass = "changeit"; //default
            }
        }
        return masterPass;
    }

    private String getFromPasswordFile(String name) {
        return passwords.get(name);
    }

    boolean isValidAnswer(String val) {
        return val.equalsIgnoreCase("yes") || val.equalsIgnoreCase("no")
                || val.equalsIgnoreCase("y") || val.equalsIgnoreCase("n");
    }

    /**
     * Method to delete files and directories on remote host
     * 'nodes' directory is not considered for deletion since it would contain
     * configuration information.
     * @param sftpClient sftp client instance
     * @param dasFiles file layout on DAS
     * @param dir directory to be removed
     * @param force true means delete all files, false means leave non-GlassFish files
     *              untouched
     * @throws IOException in case of error
     */
    // byron XXXX
    void deleteRemoteFiles(SFTPClient sftpClient, List<String> dasFiles, String dir, boolean force)
            throws IOException {

        for (SFTPv3DirectoryEntry directoryEntry : (List<SFTPv3DirectoryEntry>) sftpClient.ls(dir)) {
            if (directoryEntry.filename.equals(".") || directoryEntry.filename.equals("..")
                    || directoryEntry.filename.equals("nodes")) {
                continue;
            }
            else if (directoryEntry.attributes.isDirectory()) {
                String f1 = dir + "/" + directoryEntry.filename;
                deleteRemoteFiles(sftpClient, dasFiles, f1, force);
                //only if file is present in DAS, it is targeted for removal on remote host
                //using force deletes all files on remote host
                if (force) {
                    logger.fine("Force removing directory " + f1);
                    if (isRemoteDirectoryEmpty(sftpClient, f1)) {
                        sftpClient.rmdir(f1);
                    }
                }
                else {
                    if (dasFiles.contains(f1)) {
                        if (isRemoteDirectoryEmpty(sftpClient, f1)) {
                            sftpClient.rmdir(f1);
                        }
                    }
                }
            }
            else {
                String f2 = dir + "/" + directoryEntry.filename;
                if (force) {
                    logger.fine("Force removing file " + f2);
                    sftpClient.rm(f2);
                }
                else {
                    if (dasFiles.contains(f2))
                        sftpClient.rm(f2);
                }
            }
        }
    }

    /**
     * Method to check if specified remote directory contains files
     *
     * @param sftp SFTP client handle
     * @param file path to remote directory
     * @return true if empty, false otherwise
     * @throws IOException
     */
    boolean isRemoteDirectoryEmpty(SFTPClient sftp, String file) throws IOException {
        List<SFTPv3DirectoryEntry> l = (List<SFTPv3DirectoryEntry>) sftp.ls(file);
        if (l.size() > 2)
            return false;
        return true;
    }

    /**
     * Remove trailing slash from a path string
     * @param s
     * @return
     */
    String removeTrailingSlash(String s) {
        if (!StringUtils.ok(s))
            return s;

        if (s.endsWith("/")) {
            s = s.substring(0, s.length() - 1);
        }
        return s;
    }

    /**
     * Obtains the real password from the domain specific keystore given an alias
     * @param host host that we are connecting to
     * @param alias password alias of form ${ALIAS=xxx}
     * @return real password of ssh user, null if not found
     */
    String expandPasswordAlias(String host, String alias, boolean verifyConn) {
        String expandedPassword = null;
        boolean connStatus = false;

        try {
            File domainsDirFile = DomainDirs.getDefaultDomainsDir();

            //get the list of domains
            File[] files = domainsDirFile.listFiles(new FileFilter() {
                public boolean accept(File f) {
                    return f.isDirectory();
                }
            });

            for (File f : files) {
                //the following property is required for initializing the password helper
                System.setProperty(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY, f.getAbsolutePath());
                try {
                    final PasswordAdapter pa = new PasswordAdapter(null);
                    final boolean exists = pa.aliasExists(alias);
                    if (exists) {
                        String mPass = getMasterPassword(f.getName());
                        expandedPassword = new PasswordAdapter(mPass.toCharArray()).getPasswordForAlias(alias);
                    }
                }
                catch (Exception e) {
                    if (logger.isLoggable(Level.FINER)) {
                        logger.finer(StringUtils.cat(": ", alias, e.getMessage()));
                    }
                    logger.warning(Strings.get("GetPasswordFailure", f.getName()));
                    continue;
                }

                if (expandedPassword != null) {
                    SSHLauncher sshL = new SSHLauncher();
                    if (host != null) {
                        sshpassword = expandedPassword;
                        sshL.init(getRemoteUser(), host, getRemotePort(), sshpassword, null, null, logger);
                        connStatus = sshL.checkPasswordAuth();
                        if (!connStatus) {
                            logger.warning(Strings.get("PasswordAuthFailure", f.getName()));
                        }
                    }
                    else {
                        sshkeypassphrase = expandedPassword;
                        if (verifyConn) {
                            sshL.init(getRemoteUser(), hosts[0], getRemotePort(), sshpassword, getSshKeyFile(), sshkeypassphrase, logger);
                            connStatus = sshL.checkConnection();
                            if (!connStatus) {
                                logger.warning(Strings.get("PasswordAuthFailure", f.getName()));
                            }
                        }
                    }

                    if (connStatus) {
                        break;
                    }
                }
            }
        }
        catch (IOException ioe) {
            if (logger.isLoggable(Level.FINER)) {
                logger.finer(ioe.getMessage());
            }
        }
        return expandedPassword;
    }

    /**
     * This method first obtains a list of files under the product installation
     * directory. It then modifies each path by prepending it with remote install dir path.
     * For ex. glassfish/lib/appserv-rt.jar becomes
     * <remote-install-path>/glassfish/lib/appserv-rt.jar
     * @return List of files and directories
     * @throws IOException
     */
    List<String> getListOfInstallFiles(String installDir) throws IOException {
        String ins = resolver.resolve("${com.sun.aas.productRoot}");
        Set files = FileUtils.getAllFilesAndDirectoriesUnder(new File(ins));
        logger.finer("Total number of files under " + ins + " = " + files.size());
        String remoteDir = installDir;
        if (!installDir.endsWith("/")) {
            remoteDir = remoteDir + "/";
        }
        List<String> modList = new ArrayList<String>();
        for (Object f : files) {
            modList.add(remoteDir + FileUtils.makeForwardSlashes(((File) f).getPath()));
        }
        return modList;
    }

    /**
     * Check for existence of key file.
     * @param file
     * @throws CommandException
     */
    void validateKey(String file) throws CommandException {
        File f = new File(file);
        if (!f.exists()) {
            throw new CommandException(Strings.get("KeyDoesNotExist", file));
        }
    }
}
TOP

Related Classes of com.sun.enterprise.admin.cli.cluster.NativeRemoteCommandsBase

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.