From 9b7d2a697ee49716096da22ed27c09db9b5e3dc2 Mon Sep 17 00:00:00 2001 From: William Brafford Date: Tue, 16 Jun 2020 16:18:27 -0400 Subject: [PATCH] Enable TTY password OS tests, plus refactoring (#57759) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../test/KeystoreManagementTests.java | 38 +++++++++---------- .../packaging/test/PackageTests.java | 2 +- .../packaging/test/PackagingTestCase.java | 33 ++++++++-------- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/qa/os/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java b/qa/os/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java index c547aee9d8678..8dd61ad790895 100644 --- a/qa/os/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java +++ b/qa/os/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java @@ -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; @@ -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(); @@ -153,28 +152,27 @@ 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())); @@ -182,25 +180,24 @@ public void test42KeystorePasswordOnTty() throws Exception { 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))); } @@ -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"); @@ -229,8 +225,7 @@ public void test50KeystorePasswordFromFile() throws Exception { Path esKeystorePassphraseFile = installation.config.resolve("eks"); rmKeystoreIfExists(); - createKeystore(); - setKeystorePassword(password); + createKeystore(password); assertPasswordProtectedKeystore(); @@ -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"); @@ -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"); @@ -406,6 +402,10 @@ private void createKeystore() throws Exception { throw new RuntimeException(e); } } + + if (password != null) { + setKeystorePassword(password); + } } private void rmKeystoreIfExists() { diff --git a/qa/os/src/test/java/org/elasticsearch/packaging/test/PackageTests.java b/qa/os/src/test/java/org/elasticsearch/packaging/test/PackageTests.java index 40c50c518c55f..3f99fdd42095f 100644 --- a/qa/os/src/test/java/org/elasticsearch/packaging/test/PackageTests.java +++ b/qa/os/src/test/java/org/elasticsearch/packaging/test/PackageTests.java @@ -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]")); diff --git a/qa/os/src/test/java/org/elasticsearch/packaging/test/PackagingTestCase.java b/qa/os/src/test/java/org/elasticsearch/packaging/test/PackagingTestCase.java index 2f28fba3105ae..41baa1dc152ae 100644 --- a/qa/os/src/test/java/org/elasticsearch/packaging/test/PackagingTestCase.java +++ b/qa/os/src/test/java/org/elasticsearch/packaging/test/PackagingTestCase.java @@ -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(); @@ -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); @@ -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) {