All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dtolabs.rundeck.plugin.overthere.OTWinRMNodeExecutor Maven / Gradle / Ivy

package com.dtolabs.rundeck.plugin.overthere;

import com.dtolabs.rundeck.core.common.Framework;
import com.dtolabs.rundeck.core.common.FrameworkProject;
import com.dtolabs.rundeck.core.common.INodeEntry;
import com.dtolabs.rundeck.core.dispatcher.DataContextUtils;
import com.dtolabs.rundeck.core.execution.ExecutionContext;
import com.dtolabs.rundeck.core.execution.service.NodeExecutor;
import com.dtolabs.rundeck.core.execution.service.NodeExecutorResult;
import com.dtolabs.rundeck.core.execution.service.NodeExecutorResultImpl;
import com.dtolabs.rundeck.core.execution.workflow.steps.FailureReason;
import com.dtolabs.rundeck.core.execution.workflow.steps.StepFailureReason;
import com.dtolabs.rundeck.core.execution.workflow.steps.node.NodeStepFailureReason;
import com.dtolabs.rundeck.core.plugins.Plugin;
import com.dtolabs.rundeck.core.plugins.configuration.Describable;
import com.dtolabs.rundeck.core.plugins.configuration.Description;
import com.dtolabs.rundeck.core.plugins.configuration.PropertyUtil;
import com.dtolabs.rundeck.core.Constants;
import com.dtolabs.rundeck.plugins.descriptions.PluginDescription;
import com.dtolabs.rundeck.plugins.util.DescriptionBuilder;
import com.xebialabs.overthere.*;
import com.xebialabs.overthere.cifs.CifsConnectionBuilder;
import com.xebialabs.overthere.cifs.CifsConnectionType;
import com.xebialabs.overthere.cifs.WinrmHttpsCertificateTrustStrategy;
import com.xebialabs.overthere.cifs.WinrmHttpsHostnameVerificationStrategy;
import com.xebialabs.overthere.cifs.winrm.WinRmRuntimeIOException;
import com.xebialabs.overthere.util.ConsoleOverthereExecutionOutputHandler;
import com.xebialabs.overthere.util.DefaultAddressPortMapper;

import java.util.*;

import static com.xebialabs.overthere.ConnectionOptions.*;
import static com.xebialabs.overthere.OperatingSystemFamily.WINDOWS;

/**
 * Executes a command via WinRM. Subclass to extend, there are places to alter the generation of user@realm, and to
 * alter the password resolution mechanism.
 * See {@link #getKerberosUsername(com.dtolabs.rundeck.plugin.overthere.OTWinRMNodeExecutor.ConnectionOptionsBuilder)}
 * and
 * {@link #getClearAuthPassword(com.dtolabs.rundeck.plugin.overthere.OTWinRMNodeExecutor.ConnectionOptionsBuilder)}.
 *
 * The connection options can be altered as well by overriding {@link #willUseConnectionOptions(com.xebialabs.overthere.ConnectionOptions)}.
 */
@Plugin(name = OTWinRMNodeExecutor.SERVICE_PROVIDER_TYPE, service = "NodeExecutor")
public class OTWinRMNodeExecutor implements NodeExecutor, Describable {
    public static final String SERVICE_PROVIDER_TYPE = "overthere-winrm";

    public static final int DEFAULT_WINRM_CONNECTION_TIMEOUT = 15000;
    public static final boolean DEFAULT_WINRM_CONNECTION_ENCRYPTED = true;
    public static final String WINRM_PASSWORD_OPTION = "winrm-password-option";
    public static final String DEFAULT_WINRM_PASSWORD_OPTION = "winrmPassword";
    public static final int DEFAULT_HTTPS_PORT = 5986;
    public static final int DEFAULT_HTTP_PORT = 5985;
    public static final String WINRM_CONNECTION_TIMEOUT_PROPERTY = "winrm-connection-timeout";
    public static final String WINRM_USER = "winrm-user";
    public static final String WINRM_PORT = "winrm-port";
    public static final String WINRM_AUTH_TYPE = "winrm-auth-type";
    public static final String WINRM_CERT_TRUST = "winrm-cert-trust";
    public static final String WINRM_HOSTNAME_TRUST = "winrm-hostname-trust";
    public static final String WINRM_PROTOCOL = "winrm-protocol";
    public static final String AUTH_TYPE_KERBEROS = "kerberos";
    public static final String AUTH_TYPE_BASIC = "basic";
    public static final String WINRM_PROTOCOL_HTTPS = "https";
    public static final String WINRM_PROTOCOL_HTTP = "http";
    public static final String WINRM_SPN_ADD_PORT = "winrm-spn-add-port";
    public static final String WINRM_SPN_USE_HTTP = "winrm-spn-use-http";
    public static final String WINRM_LOCALE = "winrm-locale";
    public static final String WINRM_TIMEOUT = "winrm-timeout";

    public static final String HOSTNAME_TRUST_BROWSER_COMPATIBLE = "browser-compatible";
    public static final String HOSTNAME_TRUST_STRICT = "strict";
    public static final String HOSTNAME_TRUST_ALL = "all";


    public static final String CERT_TRUST_DEFAULT = "default";
    public static final String CERT_TRUST_ALL = "all";
    public static final String CERT_TRUST_SELF_SIGNED = "self-signed";

    public static final String DEFAULT_AUTH_TYPE = AUTH_TYPE_KERBEROS;
    public static final String DEBUG_KERBEROS_AUTH = "winrm-kerberos-debug";
    public static final Boolean DEFAULT_DEBUG_KERBEROS_AUTH = false;
    public static final String DEFAULT_WINRM_PROTOCOL = WINRM_PROTOCOL_HTTPS;

    public static final WinrmHttpsCertificateTrustStrategy DEFAULT_CERT_TRUST =
        WinrmHttpsCertificateTrustStrategy.STRICT;
    public static final WinrmHttpsHostnameVerificationStrategy DEFAULT_HOSTNAME_VERIFY =
        WinrmHttpsHostnameVerificationStrategy.BROWSER_COMPATIBLE;

    //Config properties for GUI
    public static final String CONFIG_AUTHENTICATION = "authentication";
    public static final String CONFIG_PROTOCOL = "protocol";
    public static final String CONFIG_CERT_TRUST = "certTrust";
    public static final String CONFIG_HOSTNAME_VERIFY = "hostnameVerify";
    public static final String CONFIG_SPN_ADD_PORT = "spnAddPort";
    public static final String CONFIG_SPN_USE_HTTP = "spnUseHttp";
    public static final String CONFIG_LOCALE = "locale";
    public static final String CONFIG_WINRM_TIMEOUT = "winrmTimeout";
    private static final String CONFIG_TIMEOUT = "timeout";

    private Framework framework;
    private static final String PROJ_PROP_PREFIX = "project.";
    private static final String FWK_PROP_PREFIX = "framework.";

    public OTWinRMNodeExecutor(final Framework framework) {
        this.framework = framework;
    }

    static final Description DESC = DescriptionBuilder.builder()
            .name(SERVICE_PROVIDER_TYPE)
            .title("WinRM")
            .description("Executes a command on a remote windows node via WinRM.")
            .property(PropertyUtil.select(CONFIG_AUTHENTICATION, "Authentication",
                    "Authentication mechanism to use",
                    true, DEFAULT_AUTH_TYPE, Arrays.asList(AUTH_TYPE_KERBEROS, AUTH_TYPE_BASIC)))

            .property(PropertyUtil.select(CONFIG_PROTOCOL, "WinRM Protocol",
                    "HTTP Protocol",
                    true, DEFAULT_WINRM_PROTOCOL, Arrays.asList(WINRM_PROTOCOL_HTTP, WINRM_PROTOCOL_HTTPS)))

            .property(PropertyUtil.select(CONFIG_CERT_TRUST, "HTTPS Certificate Trust",
                    "Strategy for certificate trust (Kerberos only)",
                    false, DEFAULT_CERT_TRUST.toString(), Arrays.asList(CERT_TRUST_ALL, CERT_TRUST_SELF_SIGNED,
                    CERT_TRUST_DEFAULT)))


            .property(PropertyUtil.select(CONFIG_HOSTNAME_VERIFY, "HTTPS Hostname Verification",
                    "Strategy for hostname verification (Kerberos only)",
                    false, DEFAULT_HOSTNAME_VERIFY.toString(), Arrays.asList(HOSTNAME_TRUST_ALL,
                    HOSTNAME_TRUST_BROWSER_COMPATIBLE,
                    HOSTNAME_TRUST_STRICT)))


            .property(PropertyUtil.bool(CONFIG_SPN_ADD_PORT, "SPN adds Port",
                    "If true, add the port (e.g. 5985) to the SPN used for Kerberos Authentication.",
                    true, "false"))

            .property(PropertyUtil.bool(CONFIG_SPN_USE_HTTP, "SPN uses HTTP",
                    "If true, use HTTP instead of WSMAN for the SPN used for Kerberos Authentication.",
                    true, "false"))

            .property(PropertyUtil.string(CONFIG_LOCALE, "WinRM Locale",
                    "Locale, default: en-us.", false, null))

            .property(PropertyUtil.string(CONFIG_WINRM_TIMEOUT, "WinRM Timeout",
                    "WinRM protocol Timeout, in XML Schema Duration format. (Default: PT60.000S) see: ", false, null))

            .property(PropertyUtil.longProp(CONFIG_TIMEOUT, "Connection Timeout", "Connection timeout, " +
                    "in milliseconds. Default: 15000 (15 seconds).", false, null))

            .mapping(CONFIG_AUTHENTICATION, PROJ_PROP_PREFIX + WINRM_AUTH_TYPE)
            .mapping(CONFIG_PROTOCOL, PROJ_PROP_PREFIX + WINRM_PROTOCOL)
            .mapping(CONFIG_CERT_TRUST, PROJ_PROP_PREFIX + WINRM_CERT_TRUST)
            .mapping(CONFIG_HOSTNAME_VERIFY, PROJ_PROP_PREFIX + WINRM_HOSTNAME_TRUST)
            .mapping(CONFIG_SPN_ADD_PORT, PROJ_PROP_PREFIX + WINRM_SPN_ADD_PORT)
            .mapping(CONFIG_SPN_USE_HTTP, PROJ_PROP_PREFIX + WINRM_SPN_USE_HTTP)
            .mapping(CONFIG_LOCALE, PROJ_PROP_PREFIX + WINRM_LOCALE)
            .mapping(CONFIG_WINRM_TIMEOUT, PROJ_PROP_PREFIX + WINRM_TIMEOUT)
            .mapping(CONFIG_TIMEOUT, PROJ_PROP_PREFIX + WINRM_CONNECTION_TIMEOUT_PROPERTY)
            .build();

    public Description getDescription() {
        return DESC;
    }

    public static enum Reason implements FailureReason {
        WinRMProtocolError,
    }

    public NodeExecutorResult executeCommand(final ExecutionContext context, final String[] command,
            final INodeEntry node) {

        ConnectionOptions options = null;
        String logprompt = "[" + SERVICE_PROVIDER_TYPE + ":" + node.extractHostname() + "] ";

        if (null == context.getExecutionListener()) {
            System.out.println(logprompt + " Bad plugin context!  NULL ExecutionListener");
        }

        context.getExecutionListener().log(Constants.VERBOSE_LEVEL, logprompt + buildCommandLine(command));

        try {
            options = willUseConnectionOptions(new ConnectionOptionsBuilder(context, node, framework).build());
        } catch (ConfigurationException e) {
            context.getExecutionListener().log(Constants.ERR_LEVEL, logprompt + e.getMessage());
            return NodeExecutorResultImpl.createFailure(StepFailureReason.ConfigurationFailure, e.getMessage(), node);
        }

        context.getExecutionListener().log(Constants.VERBOSE_LEVEL, logprompt + options);

        int result = -1;
        try {
            final OverthereConnection connection = new CifsConnectionBuilder(CifsConnectionBuilder.CIFS_PROTOCOL, options,
                    new DefaultAddressPortMapper()).connect();

            try {
                result = connection.execute(ConsoleOverthereExecutionOutputHandler.sysoutHandler(),
                        ConsoleOverthereExecutionOutputHandler.syserrHandler(),
                        buildCommandLine(command));
            } finally {
                connection.close();
            }
        } catch (WinRmRuntimeIOException re) {
            String message = null;
            if (context.getLoglevel() > 2) {
                re.printStackTrace(System.err);
                message = re.getMessage();
            } else {
                message = "WinRM Error: " + re.getMessage();
            }
            context.getExecutionListener().log(Constants.ERR_LEVEL, logprompt + "failed: " + message);
            return NodeExecutorResultImpl.createFailure(Reason.WinRMProtocolError, message, re, node, -1);
        } catch (RuntimeIOException re) {
            String message = null;
            if (context.getLoglevel() > 2) {
                re.printStackTrace(System.err);
                message = re.getMessage();
            } else {
                message = "runtime exception: " + re;
            }
            context.getExecutionListener().log(Constants.ERR_LEVEL, logprompt + "failed: " + message);
            return NodeExecutorResultImpl.createFailure(StepFailureReason.IOFailure, message, re, node, -1);
        }


        final int resultCode = result;
        final boolean status = resultCode == 0;

        if (status) {
            return NodeExecutorResultImpl.createSuccess(node);
        } else {
            context.getExecutionListener().log(Constants.ERR_LEVEL, logprompt + "failed: exit code: " + resultCode);
            return NodeExecutorResultImpl.createFailure(NodeStepFailureReason.NonZeroResultCode,
                    "[" + SERVICE_PROVIDER_TYPE + "] result code: " + resultCode, node, resultCode);
        }
    }

    /**
     * Create the {@link CmdLine} to run from the input string array, the default behavior is to use {@link #buildCmdLineRaw(String...)}
     * @param command
     * @return
     */
    protected CmdLine buildCommandLine(String[] command) {
        return buildCmdLineRaw(command);
    }

    /**
     * Called before connecting with the ConnectionnOptions that will be used, which can be altered here by a subclass.
     *
     * @param options configured options
     *
     * @return the ConnectionOptions to use
     */
    protected ConnectionOptions willUseConnectionOptions(final ConnectionOptions options) throws ConfigurationException {
        return options;
    }



    /**
     * Build a CmdLine without escaping any part, using Raw arguments
     *
     * @param args the regular arguments which will be added without escaping
     *
     * @return the created command line
     */
    public static CmdLine buildCmdLineRaw(String... args) {
        CmdLine cmdLine = new CmdLine();
        for (String s : args) {
            cmdLine.addRaw(s);
        }
        return cmdLine;
    }

    static String evaluateSecureOption(final String optionName, final ExecutionContext context) {
        if (null == optionName) {
            return null;
        }
        if (null == context.getPrivateDataContext()) {
            return null;
        }
        final String[] opts = optionName.split("\\.", 2);
        String dataset = null;
        String optname = null;
        if (null != opts && 2 == opts.length) {
            dataset = opts[0];
            optname = opts[1];
        } else if (null != opts && 1 == opts.length) {
            dataset = "option";
            optname = opts[0];
        }
        final Map option = context.getPrivateDataContext().get(dataset);
        if (null != option) {
            return option.get(optname);
        }
        return null;
    }

    /**
     * Resolve a node/project/framework property by first checking node attributes named X, then project properties
     * named "project.X", then framework properties named "framework.X". If none of those exist, return the default
     * value
     */
    private static String resolveProperty(final String nodeAttribute, final String defaultValue, final INodeEntry node,
            final FrameworkProject frameworkProject, final Framework framework) {

        if (null != node.getAttributes().get(nodeAttribute)) {
            return node.getAttributes().get(nodeAttribute);
        } else if (frameworkProject.hasProperty(PROJ_PROP_PREFIX + nodeAttribute)
                && !"".equals(frameworkProject.getProperty(PROJ_PROP_PREFIX + nodeAttribute))) {
            return frameworkProject.getProperty(PROJ_PROP_PREFIX + nodeAttribute);
        } else if (framework.hasProperty(FWK_PROP_PREFIX + nodeAttribute)) {
            return framework.getProperty(FWK_PROP_PREFIX + nodeAttribute);
        } else {
            return defaultValue;
        }
    }

    private static int resolveIntProperty(final String attribute, final int defaultValue, final INodeEntry iNodeEntry,
            final FrameworkProject frameworkProject, final Framework framework) throws ConfigurationException {
        int value = defaultValue;
        final String string = resolveProperty(attribute, null, iNodeEntry, frameworkProject, framework);
        if (null != string) {
            try {
                value = Integer.parseInt(string);
            } catch (NumberFormatException e) {
                throw new ConfigurationException("Not a valid integer: " + attribute + ": " + string);
            }
        }
        return value;
    }

    private static long resolveLongProperty(final String attribute, final long defaultValue,
            final INodeEntry iNodeEntry,
            final FrameworkProject frameworkProject, final Framework framework) throws ConfigurationException {
        long value = defaultValue;
        final String string = resolveProperty(attribute, null, iNodeEntry, frameworkProject, framework);
        if (null != string) {
            try {
                value = Long.parseLong(string);
            } catch (NumberFormatException e) {
                throw new ConfigurationException("Not a valid long: " + attribute + ": " + string);
            }
        }
        return value;
    }

    private static boolean resolveBooleanProperty(final String attribute, final boolean defaultValue,
            final INodeEntry iNodeEntry,
            final FrameworkProject frameworkProject, final Framework framework) {
        boolean value = defaultValue;
        final String string = resolveProperty(attribute, null, iNodeEntry, frameworkProject, framework);
        if (null != string) {
            value = Boolean.parseBoolean(string);
        }
        return value;
    }

    static class ConfigurationException extends Exception {
        ConfigurationException(String s) {
            super(s);
        }

        ConfigurationException(String s, Throwable throwable) {
            super(s, throwable);
        }
    }

    protected class ConnectionOptionsBuilder {

        private ExecutionContext context;
        private INodeEntry node;
        private Framework framework;
        private FrameworkProject frameworkProject;

        ConnectionOptionsBuilder(final ExecutionContext context, final INodeEntry node, final Framework framework) {
            this.context = context;
            this.node = node;
            this.framework = framework;
            this.frameworkProject = framework.getFrameworkProjectMgr().getFrameworkProject(
                    context.getFrameworkProject());
        }

        public String getPassword() {
            final String passwordOption = resolveProperty(WINRM_PASSWORD_OPTION, DEFAULT_WINRM_PASSWORD_OPTION, getNode(),
                getFrameworkProject(), getFramework());
            return evaluateSecureOption(passwordOption, getContext());
        }

        public int getConnectionTimeout() throws ConfigurationException {
            return resolveIntProperty(WINRM_CONNECTION_TIMEOUT_PROPERTY, DEFAULT_WINRM_CONNECTION_TIMEOUT, getNode(),
                getFrameworkProject(), getFramework());
        }

        public String getUsername() {
            final String user;
            if (null != nonBlank(getNode().getUsername()) || getNode().containsUserName()) {
                user = nonBlank(getNode().getUsername());
            } else {
                user = resolveProperty(WINRM_USER, null, getNode(), getFrameworkProject(), getFramework());
            }

            if (null != user && user.contains("${")) {
                return DataContextUtils.replaceDataReferences(user, getContext().getDataContext());
            }
            return user;
        }

        public String getHostname() {
            return getNode().extractHostname();
        }

        public String getAuthType() {
            return resolveProperty(WINRM_AUTH_TYPE, DEFAULT_AUTH_TYPE, getNode(), getFrameworkProject(), getFramework());
        }

        public WinrmHttpsCertificateTrustStrategy getCertTrustStrategy() {
            String trust = resolveProperty(WINRM_CERT_TRUST, DEFAULT_CERT_TRUST.toString(),
                getNode(), getFrameworkProject(), getFramework());
            if ( trust == null )
            {
                return DEFAULT_CERT_TRUST;
            }
            if ( trust.equals(CERT_TRUST_DEFAULT))
            {
                return WinrmHttpsCertificateTrustStrategy.STRICT;
            }
            if ( trust.equals(CERT_TRUST_SELF_SIGNED))
            {
                return WinrmHttpsCertificateTrustStrategy.SELF_SIGNED;
            }
            if ( trust.equals(CERT_TRUST_ALL))
            {
                return WinrmHttpsCertificateTrustStrategy.ALLOW_ALL;
            }
            return DEFAULT_CERT_TRUST;
        }

        public WinrmHttpsHostnameVerificationStrategy getHostTrust() {
            String trust = resolveProperty(WINRM_HOSTNAME_TRUST, DEFAULT_HOSTNAME_VERIFY.toString(),
                getNode(), getFrameworkProject(), getFramework());
            if ( trust == null )
            {
                return DEFAULT_HOSTNAME_VERIFY;
            }
            if ( trust.equals(HOSTNAME_TRUST_STRICT) )
            {
                return WinrmHttpsHostnameVerificationStrategy.STRICT;
            }
            if ( trust.equals(HOSTNAME_TRUST_BROWSER_COMPATIBLE) )
            {
                return WinrmHttpsHostnameVerificationStrategy.BROWSER_COMPATIBLE;
            }
            if ( trust.equals(HOSTNAME_TRUST_ALL) )
            {
                return WinrmHttpsHostnameVerificationStrategy.ALLOW_ALL;
            }
            return DEFAULT_HOSTNAME_VERIFY;
        }

        public String getProtocol() {
            return resolveProperty(WINRM_PROTOCOL, DEFAULT_WINRM_PROTOCOL, getNode(), getFrameworkProject(), getFramework());
        }

        public Boolean isDebugKerberosAuth() {
            return resolveBooleanProperty(DEBUG_KERBEROS_AUTH, DEFAULT_DEBUG_KERBEROS_AUTH, getNode(), getFrameworkProject(),
                    getFramework());
        }

        public Boolean isWinrmSpnAddPort() {
            return resolveBooleanProperty(WINRM_SPN_ADD_PORT, false, getNode(), getFrameworkProject(),
                    getFramework());
        }

        public Boolean isWinrmSpnUseHttp() {
            return resolveBooleanProperty(WINRM_SPN_USE_HTTP, false, getNode(), getFrameworkProject(),
                    getFramework());
        }

        public String getWinrmLocale() {
            return resolveProperty(WINRM_LOCALE, null, getNode(), getFrameworkProject(), getFramework());
        }

        public String getWinrmTimeout() {
            return resolveProperty(WINRM_TIMEOUT, null, getNode(), getFrameworkProject(), getFramework());
        }

        private int getPort(final int defaultPort) throws ConfigurationException {
            // If the node entry contains a non-default port, configure the connection to use it.
            if (getNode().containsPort()) {
                try {
                    return Integer.parseInt(getNode().extractPort());
                } catch (NumberFormatException e) {
                    throw new ConfigurationException("Port number is not valid: " + getNode().extractPort(), e);
                }
            } else {
                return resolveIntProperty(WINRM_PORT, defaultPort, getNode(), getFrameworkProject(), getFramework());
            }
        }

        public ConnectionOptions build() throws ConfigurationException{
            final ConnectionOptions options = new ConnectionOptions();
            final String authType = getAuthType();
            final boolean isHttps = WINRM_PROTOCOL_HTTPS.equalsIgnoreCase(getProtocol());

            final boolean isKerberos = getUsername().indexOf("@") > 0 || AUTH_TYPE_KERBEROS.equals(authType);

            String username;
            if (isKerberos) {
                username = getKerberosUsername(this);
                options.set(CifsConnectionBuilder.WINRM_KERBEROS_DEBUG, isDebugKerberosAuth());
                options.set(CifsConnectionBuilder.WINRM_KERBEROS_ADD_PORT_TO_SPN, isWinrmSpnAddPort());
                options.set(CifsConnectionBuilder.WINRM_KERBEROS_USE_HTTP_SPN, isWinrmSpnUseHttp());
            } else {
                username = getUsername();
            }
            final String password = getClearAuthPassword(this);
            final boolean valid = null != password && !"".equals(password);
            if (!valid) {
                throw new ConfigurationException("Password was not set");
            }

            if (isHttps) {
                options.set(CifsConnectionBuilder.WINRM_HTTPS_CERTIFICATE_TRUST_STRATEGY, getCertTrustStrategy());
                options.set(CifsConnectionBuilder.WINRM_HTTPS_HOSTNAME_VERIFICATION_STRATEGY, getHostTrust());
            }

            options.set(ADDRESS, getHostname());
            options.set(USERNAME, username);
            options.set(PASSWORD, password);
            options.set(OPERATING_SYSTEM, WINDOWS);
            options.set(CONNECTION_TIMEOUT_MILLIS, getConnectionTimeout());
            options.set(PORT, getPort(isHttps ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT));
            options.set(CifsConnectionBuilder.CONNECTION_TYPE, CifsConnectionType.WINRM_INTERNAL);
            options.set(CifsConnectionBuilder.WINRM_ENABLE_HTTPS, isHttps);
            options.set(CifsConnectionBuilder.WINRM_KERBEROS_ADD_PORT_TO_SPN, isWinrmSpnAddPort());
            options.set(CifsConnectionBuilder.WINRM_KERBEROS_USE_HTTP_SPN, isWinrmSpnUseHttp());
            if (null != getWinrmLocale()) {
                options.set(CifsConnectionBuilder.WINRM_LOCALE, getWinrmLocale());
            }
            if (null != getWinrmTimeout()) {
                options.set(CifsConnectionBuilder.WINRM_TIMEMOUT, getWinrmTimeout());
            }
            return options;
        }

        public ExecutionContext getContext() {
            return context;
        }

        public INodeEntry getNode() {
            return node;
        }

        public Framework getFramework() {
            return framework;
        }

        public FrameworkProject getFrameworkProject() {
            return frameworkProject;
        }
    }

    static String nonBlank(String input) {
        if (null == input || "".equals(input.trim())) {
            return null;
        } else {
            return input.trim();
        }
    }

    /**
     * Return the cleartext user password
     *
     * @return
     */
    protected String getClearAuthPassword(final ConnectionOptionsBuilder options) {
        return options.getPassword();
    }

    /**
     * Return the full username@domain to use for kerberos authentication. The default implementation will append
     * "@HOSTNAME" if no "@DOMAIN" is present, otherwise it will convert "@domain" to "@DOMAIN" and return the value.
     *
     * @param options options builder
     *
     * @return
     */
    protected String getKerberosUsername(final ConnectionOptionsBuilder options) {
        String username = options.getUsername();
        String hostname = options.getHostname();
        if (username.indexOf("@") < 0) {
            username = username + "@" + hostname.toUpperCase();
        } else if (username.indexOf("@") > 0) {
            String domain = username.substring(username.indexOf("@"));
            username = username.substring(0, username.indexOf("@")) + domain.toUpperCase();
        }
        return username;
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy