* Enable TTY password OS tests, plus refactoring (#57759) 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. * Separate daemonization and non-daemonization case for tty Centos 6 uses a version of expect that kills the elasticsearch process when it tries to daemonize. I will fix this in future work but for now I'm replacing it with a todo.
This commit is contained in:
parent
335505c4e1
commit
958b21d727
|
@ -39,6 +39,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBoolean;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.elasticsearch.packaging.util.Archives.ARCHIVE_OWNER;
|
||||
import static org.elasticsearch.packaging.util.Archives.installArchive;
|
||||
|
@ -124,7 +125,7 @@ public class KeystoreManagementTests extends PackagingTestCase {
|
|||
|
||||
public void test20CreateKeystoreManually() throws Exception {
|
||||
rmKeystoreIfExists();
|
||||
createKeystore();
|
||||
createKeystore(null);
|
||||
|
||||
final Installation.Executables bin = installation.executables();
|
||||
verifyKeystorePermissions();
|
||||
|
@ -156,28 +157,30 @@ public class KeystoreManagementTests extends PackagingTestCase {
|
|||
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 {
|
||||
/**
|
||||
* This test simulates a user starting Elasticsearch on the command line without daemonizing
|
||||
*/
|
||||
public void test42KeystorePasswordOnTtyRunningInForeground() 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()));
|
||||
|
@ -185,25 +188,45 @@ public class KeystoreManagementTests extends PackagingTestCase {
|
|||
String password = "keystorepass";
|
||||
|
||||
rmKeystoreIfExists();
|
||||
createKeystore();
|
||||
setKeystorePassword(password);
|
||||
createKeystore(password);
|
||||
|
||||
assertPasswordProtectedKeystore();
|
||||
|
||||
awaitElasticsearchStartup(startElasticsearchTtyPassword(password, true));
|
||||
awaitElasticsearchStartup(runElasticsearchStartCommand(password, false, true));
|
||||
ServerUtils.runElasticsearchTests();
|
||||
stopElasticsearch();
|
||||
}
|
||||
|
||||
@Ignore /* Ignored for feature branch, awaits fix: https://github.com/elastic/elasticsearch/issues/49340 */
|
||||
public void test43WrongKeystorePasswordOnTty() throws Exception {
|
||||
@Ignore // awaits fix: https://github.com/elastic/elasticsearch/issues/49340
|
||||
public void test43KeystorePasswordOnTtyDaemonized() 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(password);
|
||||
|
||||
assertPasswordProtectedKeystore();
|
||||
|
||||
awaitElasticsearchStartup(runElasticsearchStartCommand(password, true, true));
|
||||
ServerUtils.runElasticsearchTests();
|
||||
stopElasticsearch();
|
||||
}
|
||||
|
||||
public void test44WrongKeystorePasswordOnTty() 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);
|
||||
// daemonization shouldn't matter for this test
|
||||
boolean daemonize = randomBoolean();
|
||||
Shell.Result result = runElasticsearchStartCommand("wrong", daemonize, true);
|
||||
// error will be on stdout for "expect"
|
||||
assertThat(result.stdout, anyOf(containsString(ERROR_INCORRECT_PASSWORD), containsString(ERROR_CORRUPTED_KEYSTORE)));
|
||||
}
|
||||
|
@ -212,14 +235,13 @@ public class KeystoreManagementTests extends PackagingTestCase {
|
|||
* If we have an encrypted keystore, we shouldn't require a password to
|
||||
* view help information.
|
||||
*/
|
||||
public void test44EncryptedKeystoreAllowsHelpMessage() throws Exception {
|
||||
public void test45EncryptedKeystoreAllowsHelpMessage() throws Exception {
|
||||
assumeTrue("users call elasticsearch directly in archive case", distribution.isArchive());
|
||||
|
||||
String password = "keystorepass";
|
||||
|
||||
rmKeystoreIfExists();
|
||||
createKeystore();
|
||||
setKeystorePassword(password);
|
||||
createKeystore(password);
|
||||
|
||||
assertPasswordProtectedKeystore();
|
||||
Shell.Result r = installation.executables().elasticsearch.run("--help");
|
||||
|
@ -232,8 +254,7 @@ public class KeystoreManagementTests extends PackagingTestCase {
|
|||
Path esKeystorePassphraseFile = installation.config.resolve("eks");
|
||||
|
||||
rmKeystoreIfExists();
|
||||
createKeystore();
|
||||
setKeystorePassword(password);
|
||||
createKeystore(password);
|
||||
|
||||
assertPasswordProtectedKeystore();
|
||||
|
||||
|
@ -268,7 +289,7 @@ public class KeystoreManagementTests extends PackagingTestCase {
|
|||
Files.write(esKeystorePassphraseFile, singletonList("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");
|
||||
|
@ -399,7 +420,8 @@ public class KeystoreManagementTests extends PackagingTestCase {
|
|||
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");
|
||||
|
@ -417,6 +439,10 @@ public class KeystoreManagementTests extends PackagingTestCase {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
setKeystorePassword(password);
|
||||
}
|
||||
}
|
||||
|
||||
private void rmKeystoreIfExists() {
|
||||
|
|
|
@ -368,7 +368,7 @@ public class PackageTests extends PackagingTestCase {
|
|||
|
||||
// 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]"));
|
||||
|
|
|
@ -217,7 +217,7 @@ public abstract class PackagingTestCase extends Assert {
|
|||
*/
|
||||
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();
|
||||
|
@ -249,14 +249,27 @@ public abstract class PackagingTestCase extends Assert {
|
|||
* 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);
|
||||
|
@ -307,21 +320,11 @@ public abstract class PackagingTestCase extends Assert {
|
|||
|
||||
/**
|
||||
* 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) {
|
||||
|
|
|
@ -241,12 +241,16 @@ public class Archives {
|
|||
final Path pidFile = installation.home.resolve("elasticsearch.pid");
|
||||
final Installation.Executables bin = installation.executables();
|
||||
|
||||
// requires the "expect" utility to be installed
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add("sudo -E -u %s %s -p %s");
|
||||
|
||||
// requires the "expect" utility to be installed
|
||||
// TODO: daemonization isn't working with expect versions prior to 5.45, but centos-6 has 5.45.1.15
|
||||
// TODO: try using pty4j to make daemonization work
|
||||
if (daemonize) {
|
||||
command.add("-d");
|
||||
}
|
||||
|
||||
String script = String.format(
|
||||
Locale.ROOT,
|
||||
"expect -c \"$(cat<<EXPECT\n"
|
||||
|
|
Loading…
Reference in New Issue