Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feature/GEODE-2019
Browse files Browse the repository at this point in the history
  • Loading branch information
Karen Miller committed Oct 20, 2016
2 parents 139c0a3 + 7e659b2 commit bc060f9
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,28 @@ public void test004StartServerFailsFastOnMissingGemFirePropertiesFile() throws I
assertTrue(resultString, resultString.contains(MessageFormat.format(CliStrings.GEODE_0_PROPERTIES_1_NOT_FOUND_MESSAGE, StringUtils.EMPTY_STRING, gemfirePropertiesFile)));
}

@Test
public void testStartServerFailsFastOnMissingPassword() throws IOException {

CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_SERVER);

String pathName = getClass().getSimpleName().concat("_").concat(getTestMethodName());
final File workingDirectory = temporaryFolder.newFolder(pathName);

command.addOption(CliStrings.START_SERVER__NAME, pathName);
command.addOption(CliStrings.START_SERVER__DIR, workingDirectory.getCanonicalPath());
command.addOption(CliStrings.START_SERVER__USERNAME, "test");

CommandResult result = executeCommand(command.toString());

assertNotNull(result);
assertEquals(Result.Status.ERROR, result.getStatus());

String resultString = toString(result);

assertTrue(resultString, resultString.contains("password must be specified"));
}

@Test
public void test005StartServerFailsFastOnMissingGemFireSecurityPropertiesFile() throws IOException {
String gemfireSecuritiesPropertiesFile = "/path/to/missing/gemfire-securities.properties";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,32 @@

import static org.apache.geode.distributed.ConfigurationProperties.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import joptsimple.OptionException;
import joptsimple.OptionParser;
import joptsimple.OptionSet;

import org.apache.geode.SystemFailure;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.partition.PartitionRegionHelper;
Expand All @@ -27,40 +53,40 @@
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.internal.GemFireVersion;
import org.apache.geode.internal.net.SocketCreator;
import org.apache.geode.internal.cache.*;
import org.apache.geode.internal.cache.AbstractCacheServer;
import org.apache.geode.internal.cache.CacheConfig;
import org.apache.geode.internal.cache.CacheServerLauncher;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.PartitionedRegion;
import org.apache.geode.internal.cache.tier.sockets.CacheServerHelper;
import org.apache.geode.internal.i18n.LocalizedStrings;
import org.apache.geode.internal.lang.ObjectUtils;
import org.apache.geode.internal.lang.StringUtils;
import org.apache.geode.internal.lang.SystemUtils;
import org.apache.geode.internal.process.*;
import org.apache.geode.internal.net.SocketCreator;
import org.apache.geode.internal.process.ClusterConfigurationNotAvailableException;
import org.apache.geode.internal.process.ConnectionFailedException;
import org.apache.geode.internal.process.ControlNotificationHandler;
import org.apache.geode.internal.process.ControllableProcess;
import org.apache.geode.internal.process.FileAlreadyExistsException;
import org.apache.geode.internal.process.MBeanInvocationFailedException;
import org.apache.geode.internal.process.PidUnavailableException;
import org.apache.geode.internal.process.ProcessController;
import org.apache.geode.internal.process.ProcessControllerFactory;
import org.apache.geode.internal.process.ProcessControllerParameters;
import org.apache.geode.internal.process.ProcessLauncherContext;
import org.apache.geode.internal.process.ProcessType;
import org.apache.geode.internal.process.StartupStatusListener;
import org.apache.geode.internal.process.UnableToControlProcessException;
import org.apache.geode.internal.util.IOUtils;
import org.apache.geode.lang.AttachAPINotFoundException;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.json.GfJsonArray;
import org.apache.geode.management.internal.cli.json.GfJsonException;
import org.apache.geode.management.internal.cli.json.GfJsonObject;
import org.apache.geode.pdx.PdxSerializer;
import joptsimple.OptionException;
import joptsimple.OptionParser;
import joptsimple.OptionSet;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import static org.apache.geode.distributed.ConfigurationProperties.SERVER_BIND_ADDRESS;
import org.apache.geode.security.AuthenticationRequiredException;
import org.apache.geode.security.GemFireSecurityException;

/**
* The ServerLauncher class is a launcher class with main method to start a GemFire Server (implying a GemFire Cache
Expand Down Expand Up @@ -730,6 +756,14 @@ public void setStatus(final String statusMessage) {

return new ServerState(this, Status.ONLINE);
}
catch(AuthenticationRequiredException e){
failOnStart(e);
throw new AuthenticationRequiredException("user/password required. Please start your server with --user and --password. "+ e.getMessage());
}
catch(GemFireSecurityException e){
failOnStart(e);
throw new GemFireSecurityException(e.getMessage());
}
catch (IOException e) {
failOnStart(e);
throw new RuntimeException(LocalizedStrings.Launcher_Command_START_IO_ERROR_MESSAGE.toLocalizedString(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.logging.log4j.Logger;

import org.apache.geode.GemFireConfigException;
import org.apache.geode.SystemConnectException;
import org.apache.geode.distributed.DistributedMember;
Expand Down Expand Up @@ -70,8 +72,8 @@
import org.apache.geode.distributed.internal.tcpserver.TcpClient;
import org.apache.geode.internal.Version;
import org.apache.geode.internal.i18n.LocalizedStrings;
import org.apache.geode.security.AuthenticationRequiredException;
import org.apache.geode.security.GemFireSecurityException;
import org.apache.logging.log4j.Logger;

/**
* GMSJoinLeave handles membership communication with other processes in the
Expand Down Expand Up @@ -413,6 +415,9 @@ boolean attemptToJoin() {
|| failReason.contains("15806")) {
throw new SystemConnectException(failReason);
}
else if(failReason.contains("Failed to find credentials")){
throw new AuthenticationRequiredException(failReason);
}
throw new GemFireSecurityException(failReason);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.apache.geode.management.internal.cli.commands;

import static org.apache.geode.distributed.ConfigurationProperties.*;
import static org.apache.geode.management.internal.cli.i18n.CliStrings.START_SERVER__PASSWORD;

import java.awt.Desktop;
import java.io.BufferedReader;
Expand Down Expand Up @@ -115,6 +116,7 @@
import org.apache.geode.management.internal.configuration.domain.SharedConfigurationStatus;
import org.apache.geode.management.internal.configuration.messages.SharedConfigurationStatusRequest;
import org.apache.geode.management.internal.configuration.messages.SharedConfigurationStatusResponse;
import org.apache.geode.management.internal.security.ResourceConstants;
import org.apache.geode.security.AuthenticationFailedException;

/**
Expand Down Expand Up @@ -1498,11 +1500,28 @@ public Result startServer(@CliOption(key = CliStrings.START_SERVER__ASSIGN_BUCKE
@CliOption(key = CliStrings.START_SERVER__HTTP_SERVICE_BIND_ADDRESS,
unspecifiedDefaultValue = CacheServer.HTTP_SERVICE_DEFAULT_BIND_ADDRESS,
help = CliStrings.START_SERVER__HTTP_SERVICE_BIND_ADDRESS__HELP)
final String httpServiceBindAddress)
final String httpServiceBindAddress,
@CliOption(key = CliStrings.START_SERVER__USERNAME,
unspecifiedDefaultValue = "",
help = CliStrings.START_SERVER__USERNAME__HELP)
final String userName,
@CliOption(key = START_SERVER__PASSWORD,
unspecifiedDefaultValue = "",
help = CliStrings.START_SERVER__PASSWORD__HELP)
String passwordToUse)
// NOTICE: keep the parameters in alphabetical order based on their CliStrings.START_SERVER_* text
{

try {
// prompt for password is username is specified in the command
if (!StringUtils.isBlank(userName)) {
if (StringUtils.isBlank(passwordToUse)) {
passwordToUse = getGfsh().readPassword(START_SERVER__PASSWORD + ": ");
}
if (StringUtils.isBlank(passwordToUse)) {
return ResultBuilder.createConnectionErrorResult(CliStrings.START_SERVER__MSG__PASSWORD_MUST_BE_SPECIFIED);
}
}

if (workingDirectory == null) {
// attempt to use or make sub-directory using memberName...
File serverWorkingDirectory = new File(memberName);
Expand Down Expand Up @@ -1560,10 +1579,14 @@ public Result startServer(@CliOption(key = CliStrings.START_SERVER__ASSIGN_BUCKE
gemfireProperties.setProperty(USE_CLUSTER_CONFIGURATION, StringUtils.valueOf(requestSharedConfiguration, Boolean.TRUE.toString()));
gemfireProperties.setProperty(LOCK_MEMORY, StringUtils.valueOf(lockMemory, StringUtils.EMPTY_STRING));
gemfireProperties.setProperty(OFF_HEAP_MEMORY_SIZE, StringUtils.valueOf(offHeapMemorySize, StringUtils.EMPTY_STRING));

gemfireProperties.setProperty(START_DEV_REST_API, StringUtils.valueOf(startRestApi, StringUtils.EMPTY_STRING));
gemfireProperties.setProperty(HTTP_SERVICE_PORT, StringUtils.valueOf(httpServicePort, StringUtils.EMPTY_STRING));
gemfireProperties.setProperty(HTTP_SERVICE_BIND_ADDRESS, StringUtils.valueOf(httpServiceBindAddress, StringUtils.EMPTY_STRING));
// if username is specified in the command line, it will overwrite what's set in the properties file
if(!StringUtils.isBlank(userName)){
gemfireProperties.setProperty(ResourceConstants.USER_NAME, userName);
gemfireProperties.setProperty(ResourceConstants.PASSWORD, passwordToUse);
}


// read the OSProcess enable redirect system property here -- TODO: replace with new GFSH argument
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,6 @@
import org.apache.geode.management.internal.web.shell.RestHttpOperationInvoker;
import org.apache.geode.security.AuthenticationFailedException;

import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.ExitShellRequest;
import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;

import static org.apache.geode.distributed.ConfigurationProperties.*;

/**
*
* @since GemFire 7.0
Expand Down Expand Up @@ -200,7 +192,7 @@ public Result connect(
try {
if (userName != null && userName.length() > 0) {
if (passwordToUse == null || passwordToUse.length() == 0) {
passwordToUse = this.readPassword(gfsh, "password: ");
passwordToUse = gfsh.readPassword(CliStrings.CONNECT__PASSWORD + ": ");
}
if (passwordToUse == null || passwordToUse.length() == 0) {
return ResultBuilder.createConnectionErrorResult(CliStrings.CONNECT__MSG__JMX_PASSWORD_MUST_BE_SPECIFIED);
Expand Down Expand Up @@ -282,8 +274,8 @@ private Result httpConnect(Map<String, String> sslConfigProps, boolean useSsl, S

// otherwise, prompt for username and password and retry the conenction
try {
userName = this.readText(gfsh, "username: ");
passwordToUse = this.readPassword(gfsh, "password: ");
userName = gfsh.readText(CliStrings.CONNECT__USERNAME + ": ");
passwordToUse = gfsh.readPassword(CliStrings.CONNECT__PASSWORD + ": ");
return httpConnect(sslConfigProps, useSsl, url, userName, passwordToUse);
}
catch (IOException ioe) {
Expand Down Expand Up @@ -370,8 +362,8 @@ private Result jmxConnect(Map<String, String> sslConfigProps,

// otherwise, prompt for username and password and retry the conenction
try {
userName = this.readText(gfsh, "username: ");
passwordToUse = this.readPassword(gfsh, "password: ");
userName = gfsh.readText(CliStrings.CONNECT__USERNAME + ": ");
passwordToUse = gfsh.readPassword(CliStrings.CONNECT__PASSWORD + ": ");
return jmxConnect(sslConfigProps, hostPortToConnect, null, useSsl, userName, passwordToUse, gfSecurityPropertiesPath, true);
}
catch (IOException ioe) {
Expand Down Expand Up @@ -522,15 +514,15 @@ else if (useSsl && gfSecurityPropertiesPath == null) {

if (numTimesPrompted > 0) {
//NOTE: sslConfigProps map was empty
keystoreToUse = readText(gfshInstance, CliStrings.CONNECT__KEY_STORE + ": ");
keystoreToUse = gfshInstance.readText(CliStrings.CONNECT__KEY_STORE + ": ");
}
if (keystoreToUse != null && keystoreToUse.length() > 0) {
if (keystorePasswordToUse == null || keystorePasswordToUse.length() == 0) {
// Check whether specified in gfsecurity props earlier
keystorePasswordToUse = sslConfigProps.get(Gfsh.SSL_KEYSTORE_PASSWORD);
if (keystorePasswordToUse == null || keystorePasswordToUse.length() == 0) {
// not even in properties file, prompt user for it
keystorePasswordToUse = readPassword(gfshInstance, CliStrings.CONNECT__KEY_STORE_PASSWORD + ": ");
keystorePasswordToUse = gfshInstance.readPassword(CliStrings.CONNECT__KEY_STORE_PASSWORD + ": ");
sslConfigProps.put(Gfsh.SSL_KEYSTORE_PASSWORD, keystorePasswordToUse);
}
}
Expand All @@ -541,15 +533,15 @@ else if (useSsl && gfSecurityPropertiesPath == null) {
}

if (numTimesPrompted > 0) {
truststoreToUse = readText(gfshInstance, CliStrings.CONNECT__TRUST_STORE + ": ");
truststoreToUse = gfshInstance.readText(CliStrings.CONNECT__TRUST_STORE + ": ");
}
if (truststoreToUse != null && truststoreToUse.length() > 0) {
if (truststorePasswordToUse == null || truststorePasswordToUse.length() == 0) {
// Check whether specified in gfsecurity props earlier?
truststorePasswordToUse = sslConfigProps.get(Gfsh.SSL_TRUSTSTORE_PASSWORD);
if (truststorePasswordToUse == null || truststorePasswordToUse.length() == 0) {
// not even in properties file, prompt user for it
truststorePasswordToUse = readPassword(gfshInstance, CliStrings.CONNECT__TRUST_STORE_PASSWORD + ": ");
truststorePasswordToUse = gfshInstance.readPassword(CliStrings.CONNECT__TRUST_STORE_PASSWORD + ": ");
sslConfigProps.put(Gfsh.SSL_TRUSTSTORE_PASSWORD, truststorePasswordToUse);
}
}
Expand All @@ -560,15 +552,15 @@ else if (useSsl && gfSecurityPropertiesPath == null) {
}

if (numTimesPrompted > 0) {
sslCiphersToUse = readText(gfshInstance, CliStrings.CONNECT__SSL_CIPHERS + ": ");
sslCiphersToUse = gfshInstance.readText(CliStrings.CONNECT__SSL_CIPHERS + ": ");
}
if (sslCiphersToUse != null && sslCiphersToUse.length() > 0) {
//sslConfigProps.put(DistributionConfig.CLUSTER_SSL_CIPHERS_NAME, sslCiphersToUse);
sslConfigProps.put(Gfsh.SSL_ENABLED_CIPHERS, sslCiphersToUse);
}

if (numTimesPrompted > 0) {
sslProtocolsToUse = readText(gfshInstance, CliStrings.CONNECT__SSL_PROTOCOLS + ": ");
sslProtocolsToUse = gfshInstance.readText(CliStrings.CONNECT__SSL_PROTOCOLS + ": ");
}
if (sslProtocolsToUse != null && sslProtocolsToUse.length() > 0) {
//sslConfigProps.put(DistributionConfig.CLUSTER_SSL_PROTOCOLS_NAME, sslProtocolsToUse);
Expand All @@ -585,24 +577,6 @@ private static String getGfshLogsCheckMessage(String logFilePath) {
return CliStrings.format(CliStrings.GFSH__PLEASE_CHECK_LOGS_AT_0, logFilePath);
}

private String readText(Gfsh gfsh, String textToPrompt) throws IOException {
if (!gfsh.isHeadlessMode() || !gfsh.isQuietMode()) {
return gfsh.interact(textToPrompt);
}
else {
return null;
}
}

private String readPassword(Gfsh gfsh, String textToPrompt) throws IOException {
if (!gfsh.isHeadlessMode() || !gfsh.isQuietMode()) {
return gfsh.readWithMask(textToPrompt, '*');
}
else {
return null;
}
}

/* package-private */
static Map<String, String> loadPropertiesFromURL(URL gfSecurityPropertiesUrl) {
Map<String, String> propsMap = Collections.emptyMap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
*/
package org.apache.geode.management.internal.cli.i18n;

import static org.apache.geode.distributed.ConfigurationProperties.*;

import java.text.MessageFormat;

import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.distributed.ConfigurationProperties;
Expand All @@ -24,10 +28,6 @@
import org.apache.geode.internal.cache.xmlcache.CacheXml;
import org.apache.geode.management.internal.cli.shell.Gfsh;

import java.text.MessageFormat;

import static org.apache.geode.distributed.ConfigurationProperties.*;

/**-
* * Contains 'String' constants used as key to the Localized strings to be used
* in classes under <code>org.apache.geode.management.internal.cli</code>
Expand Down Expand Up @@ -2203,6 +2203,11 @@ public class CliStrings {
public static final String START_SERVER__HTTP_SERVICE_PORT__HELP = "Port on which HTTP Service will listen on";
public static final String START_SERVER__HTTP_SERVICE_BIND_ADDRESS = "http-service-bind-address";
public static final String START_SERVER__HTTP_SERVICE_BIND_ADDRESS__HELP = "The IP address on which the HTTP Service will be bound. By default, the Server is bound to all local addresses.";
public static final String START_SERVER__USERNAME = "user";
public static final String START_SERVER__USERNAME__HELP = "User name to securely connect to the cluster. If the --password parameter is not specified then it will be prompted for.";
public static final String START_SERVER__PASSWORD = "password";
public static final String START_SERVER__PASSWORD__HELP = "Password to securely connect to the cluster.";
public static final String START_SERVER__MSG__PASSWORD_MUST_BE_SPECIFIED = "password must be specified.";
/**
* Creates a MessageFormat with the given pattern and uses it to format the given argument.
*
Expand Down
Loading

0 comments on commit bc060f9

Please sign in to comment.