Skip to content

Commit

Permalink
Enable TTY password OS tests, plus refactoring (elastic#57759)
Browse files Browse the repository at this point in the history
Two keystore tests were unintentionally ignored when the
password-protected keystore work was merged. I've reënabled those tests
here.

I've also refactored the test methods a little bit to reduce the API
surface: instead of having a "startElasticsearchTtyPassword" method and
a "startElasticsearchStandardInputPassword" method, I've made a single
"startElasticsearch" method with a "useTty" boolean argument.
  • Loading branch information
williamrandolph authored Jun 16, 2020
1 parent 3bf1b86 commit 9b7d2a6
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.elasticsearch.packaging.util.Platforms;
import org.elasticsearch.packaging.util.ServerUtils;
import org.elasticsearch.packaging.util.Shell;
import org.junit.Ignore;

import java.io.IOException;
import java.nio.file.Files;
Expand Down Expand Up @@ -121,7 +120,7 @@ public void test12InstallDockerDistribution() throws Exception {

public void test20CreateKeystoreManually() throws Exception {
rmKeystoreIfExists();
createKeystore();
createKeystore(null);

final Installation.Executables bin = installation.executables();
verifyKeystorePermissions();
Expand Down Expand Up @@ -153,54 +152,52 @@ public void test40KeystorePasswordOnStandardInput() throws Exception {
String password = "^|<>\\&exit"; // code insertion on Windows if special characters are not escaped

rmKeystoreIfExists();
createKeystore();
setKeystorePassword(password);
createKeystore(password);

assertPasswordProtectedKeystore();

awaitElasticsearchStartup(startElasticsearchStandardInputPassword(password, true));
awaitElasticsearchStartup(runElasticsearchStartCommand(password, true, false));
ServerUtils.runElasticsearchTests();
stopElasticsearch();
}

public void test41WrongKeystorePasswordOnStandardInput() {
public void test41WrongKeystorePasswordOnStandardInput() throws Exception {
assumeTrue("packages will use systemd, which doesn't handle stdin", distribution.isArchive());
assumeThat(installation, is(notNullValue()));

assertPasswordProtectedKeystore();

Shell.Result result = startElasticsearchStandardInputPassword("wrong", false);
Shell.Result result = runElasticsearchStartCommand("wrong", false, false);
assertElasticsearchFailure(result, Arrays.asList(ERROR_INCORRECT_PASSWORD, ERROR_CORRUPTED_KEYSTORE), null);
}

@Ignore /* Ignored for feature branch, awaits fix: https://github.com/elastic/elasticsearch/issues/49340 */
public void test42KeystorePasswordOnTty() throws Exception {
/* Windows issue awaits fix: https://github.com/elastic/elasticsearch/issues/49340 */
assumeTrue("expect command isn't on Windows", distribution.platform != Distribution.Platform.WINDOWS);
assumeTrue("packages will use systemd, which doesn't handle stdin", distribution.isArchive());
assumeThat(installation, is(notNullValue()));

String password = "keystorepass";

rmKeystoreIfExists();
createKeystore();
setKeystorePassword(password);
createKeystore(password);

assertPasswordProtectedKeystore();

awaitElasticsearchStartup(startElasticsearchTtyPassword(password, true));
awaitElasticsearchStartup(runElasticsearchStartCommand(password, true, true));
ServerUtils.runElasticsearchTests();
stopElasticsearch();
}

@Ignore /* Ignored for feature branch, awaits fix: https://github.com/elastic/elasticsearch/issues/49340 */
public void test43WrongKeystorePasswordOnTty() throws Exception {
/* Windows issue awaits fix: https://github.com/elastic/elasticsearch/issues/49340 */
assumeTrue("expect command isn't on Windows", distribution.platform != Distribution.Platform.WINDOWS);
assumeTrue("packages will use systemd, which doesn't handle stdin", distribution.isArchive());
assumeThat(installation, is(notNullValue()));

assertPasswordProtectedKeystore();

Shell.Result result = startElasticsearchTtyPassword("wrong", false);
Shell.Result result = runElasticsearchStartCommand("wrong", false, true);
// error will be on stdout for "expect"
assertThat(result.stdout, anyOf(containsString(ERROR_INCORRECT_PASSWORD), containsString(ERROR_CORRUPTED_KEYSTORE)));
}
Expand All @@ -215,8 +212,7 @@ public void test44EncryptedKeystoreAllowsHelpMessage() throws Exception {
String password = "keystorepass";

rmKeystoreIfExists();
createKeystore();
setKeystorePassword(password);
createKeystore(password);

assertPasswordProtectedKeystore();
Shell.Result r = installation.executables().elasticsearch.run("--help");
Expand All @@ -229,8 +225,7 @@ public void test50KeystorePasswordFromFile() throws Exception {
Path esKeystorePassphraseFile = installation.config.resolve("eks");

rmKeystoreIfExists();
createKeystore();
setKeystorePassword(password);
createKeystore(password);

assertPasswordProtectedKeystore();

Expand Down Expand Up @@ -265,7 +260,7 @@ public void test51WrongKeystorePasswordFromFile() throws Exception {
Files.write(esKeystorePassphraseFile, List.of("wrongpassword"));

Packages.JournaldWrapper journaldWrapper = new Packages.JournaldWrapper(sh);
Shell.Result result = runElasticsearchStartCommand(false);
Shell.Result result = runElasticsearchStartCommand(null, false, false);
assertElasticsearchFailure(result, Arrays.asList(ERROR_INCORRECT_PASSWORD, ERROR_CORRUPTED_KEYSTORE), journaldWrapper);
} finally {
sh.run("sudo systemctl unset-environment ES_KEYSTORE_PASSPHRASE_FILE");
Expand Down Expand Up @@ -388,7 +383,8 @@ private Path getKeystoreFileFromDockerContainer(String password, Path dockerKeys
return tempDirectory.resolve("elasticsearch.keystore");
}

private void createKeystore() throws Exception {
/** Create a keystore. Provide a password to password-protect it, otherwise use null */
private void createKeystore(String password) throws Exception {
Path keystore = installation.config("elasticsearch.keystore");
final Installation.Executables bin = installation.executables();
bin.keystoreTool.run("create");
Expand All @@ -406,6 +402,10 @@ private void createKeystore() throws Exception {
throw new RuntimeException(e);
}
}

if (password != null) {
setKeystorePassword(password);
}
}

private void rmKeystoreIfExists() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ public void test90DoNotCloseStderrWhenQuiet() throws Exception {

// Make sure we don't pick up the journal entries for previous ES instances.
Packages.JournaldWrapper journald = new Packages.JournaldWrapper(sh);
runElasticsearchStartCommand(true);
runElasticsearchStartCommand(null, true, false);
final Result logs = journald.getLogs();

assertThat(logs.stdout, containsString("Failed to load settings from [elasticsearch.yml]"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ protected static void install() throws Exception {
*/
protected void assertWhileRunning(Platforms.PlatformAction assertions) throws Exception {
try {
awaitElasticsearchStartup(runElasticsearchStartCommand(true));
awaitElasticsearchStartup(runElasticsearchStartCommand(null, true, false));
} catch (Exception e) {
if (Files.exists(installation.home.resolve("elasticsearch.pid"))) {
String pid = FileUtils.slurp(installation.home.resolve("elasticsearch.pid")).trim();
Expand Down Expand Up @@ -238,14 +238,27 @@ protected void assertWhileRunning(Platforms.PlatformAction assertions) throws Ex
* Run the command to start Elasticsearch, but don't wait or test for success.
* This method is useful for testing failure conditions in startup. To await success,
* use {@link #startElasticsearch()}.
* @param password Password for password-protected keystore, null for no password;
* this option will fail for non-archive distributions
* @param daemonize Run Elasticsearch in the background
* @param useTty Use a tty for inputting the password rather than standard input;
* this option will fail for non-archive distributions
* @return Shell results of the startup command.
* @throws Exception when command fails immediately.
*/
public Shell.Result runElasticsearchStartCommand(boolean daemonize) throws Exception {
public Shell.Result runElasticsearchStartCommand(String password, boolean daemonize, boolean useTty) throws Exception {
if (password != null) {
assertTrue("Only archives support user-entered passwords", distribution().isArchive());
}

switch (distribution.packaging) {
case TAR:
case ZIP:
return Archives.runElasticsearchStartCommand(installation, sh, null, daemonize);
if (useTty) {
return Archives.startElasticsearchWithTty(installation, sh, password, daemonize);
} else {
return Archives.runElasticsearchStartCommand(installation, sh, password, daemonize);
}
case DEB:
case RPM:
return Packages.runElasticsearchStartCommand(sh);
Expand Down Expand Up @@ -296,21 +309,11 @@ public void awaitElasticsearchStartup(Shell.Result result) throws Exception {

/**
* Start Elasticsearch and wait until it's up and running. If you just want to run
* the start command, use {@link #runElasticsearchStartCommand(boolean)}.
* the start command, use {@link #runElasticsearchStartCommand(String, boolean, boolean)}.
* @throws Exception if Elasticsearch can't start
*/
public void startElasticsearch() throws Exception {
awaitElasticsearchStartup(runElasticsearchStartCommand(true));
}

public Shell.Result startElasticsearchStandardInputPassword(String password, boolean daemonize) {
assertTrue("Only archives support passwords on standard input", distribution().isArchive());
return Archives.runElasticsearchStartCommand(installation, sh, password, daemonize);
}

public Shell.Result startElasticsearchTtyPassword(String password, boolean daemonize) throws Exception {
assertTrue("Only archives support passwords on TTY", distribution().isArchive());
return Archives.startElasticsearchWithTty(installation, sh, password, daemonize);
awaitElasticsearchStartup(runElasticsearchStartCommand(null, true, false));
}

public void assertElasticsearchFailure(Shell.Result result, String expectedMessage, Packages.JournaldWrapper journaldWrapper) {
Expand Down

0 comments on commit 9b7d2a6

Please sign in to comment.