From b47bd3adc7d3e2e71af55200aadf69ab0d1e60e8 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Mon, 14 Apr 2025 12:55:56 -0700 Subject: [PATCH] Use terminal reader in keystore add command (#126729) When reading a string value from stdin the keystore add command currently looks directly at stdin. However, stdin may also be consumed while reading the keystore password. This commit changes the add command to use the reader from the termainl instead of looking at stdin directly. closes #98115 --- .../keystore/AddStringKeyStoreCommand.java | 12 ++------ .../AddStringKeyStoreCommandTests.java | 30 ++++++------------- docs/changelog/126729.yaml | 6 ++++ 3 files changed, 17 insertions(+), 31 deletions(-) create mode 100644 docs/changelog/126729.yaml diff --git a/distribution/tools/keystore-cli/src/main/java/org/elasticsearch/cli/keystore/AddStringKeyStoreCommand.java b/distribution/tools/keystore-cli/src/main/java/org/elasticsearch/cli/keystore/AddStringKeyStoreCommand.java index a7ea6dcf7ce7..7d89879958db 100644 --- a/distribution/tools/keystore-cli/src/main/java/org/elasticsearch/cli/keystore/AddStringKeyStoreCommand.java +++ b/distribution/tools/keystore-cli/src/main/java/org/elasticsearch/cli/keystore/AddStringKeyStoreCommand.java @@ -19,13 +19,10 @@ import org.elasticsearch.common.settings.KeyStoreWrapper; import org.elasticsearch.core.CheckedFunction; import org.elasticsearch.env.Environment; -import java.io.BufferedReader; import java.io.CharArrayWriter; import java.io.Closeable; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; +import java.io.Reader; import java.util.Arrays; import java.util.List; @@ -47,11 +44,6 @@ class AddStringKeyStoreCommand extends BaseKeyStoreCommand { this.arguments = parser.nonOptions("setting names"); } - // pkg private so tests can manipulate - InputStream getStdin() { - return System.in; - } - @Override protected void executeCommand(Terminal terminal, OptionSet options, Environment env) throws Exception { final List settings = arguments.values(options); @@ -64,7 +56,7 @@ class AddStringKeyStoreCommand extends BaseKeyStoreCommand { final Closeable closeable; final CheckedFunction valueSupplier; if (options.has(stdinOption)) { - final BufferedReader stdinReader = new BufferedReader(new InputStreamReader(getStdin(), StandardCharsets.UTF_8)); + final Reader stdinReader = terminal.getReader(); valueSupplier = s -> { try (CharArrayWriter writer = new CharArrayWriter()) { int c; diff --git a/distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/AddStringKeyStoreCommandTests.java b/distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/AddStringKeyStoreCommandTests.java index 412624be1d50..1b368a7c38e0 100644 --- a/distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/AddStringKeyStoreCommandTests.java +++ b/distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/AddStringKeyStoreCommandTests.java @@ -18,18 +18,13 @@ import org.elasticsearch.cli.UserException; import org.elasticsearch.common.settings.KeyStoreWrapper; import org.elasticsearch.env.Environment; -import java.io.ByteArrayInputStream; import java.io.CharArrayWriter; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasToString; public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { - InputStream input; - @Override protected Command newCommand() { return new AddStringKeyStoreCommand() { @@ -37,11 +32,6 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { protected Environment createEnv(OptionSet options, ProcessInfo processInfo) throws UserException { return env; } - - @Override - InputStream getStdin() { - return input; - } }; } @@ -167,7 +157,7 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { String password = "keystorepassword"; KeyStoreWrapper.create().save(env.configDir(), password.toCharArray()); terminal.addSecretInput(password); - setInput("secret value 1"); + terminal.addSecretInput("secret value 1"); execute("-x", "foo"); assertSecureString("foo", "secret value 1", password); } @@ -176,7 +166,7 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { String password = "keystorepassword"; KeyStoreWrapper.create().save(env.configDir(), password.toCharArray()); terminal.addSecretInput(password); - setInput("secret value 2"); + terminal.addSecretInput("secret value 2"); execute("--stdin", "foo"); assertSecureString("foo", "secret value 2", password); } @@ -185,7 +175,7 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { String password = "keystorepassword"; KeyStoreWrapper.create().save(env.configDir(), password.toCharArray()); terminal.addSecretInput(password); - setInput(""); + terminal.addSecretInput(""); execute("-x", "foo"); assertSecureString("foo", "", password); } @@ -194,7 +184,7 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { String password = "keystorepassword"; KeyStoreWrapper.create().save(env.configDir(), password.toCharArray()); terminal.addSecretInput(password); - setInput("Typedthisandhitenter\n"); + terminal.addSecretInput("Typedthisandhitenter\n"); execute("-x", "foo"); assertSecureString("foo", "Typedthisandhitenter", password); } @@ -203,7 +193,7 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { String password = "keystorepassword"; KeyStoreWrapper.create().save(env.configDir(), password.toCharArray()); terminal.addSecretInput(password); - setInput("Typedthisandhitenter\r"); + terminal.addSecretInput("Typedthisandhitenter\r"); execute("-x", "foo"); assertSecureString("foo", "Typedthisandhitenter", password); } @@ -212,7 +202,9 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { final String password = "keystorepassword"; KeyStoreWrapper.create().save(env.configDir(), password.toCharArray()); terminal.addSecretInput(password); - setInput("bar1\nbar2\nbar3"); + terminal.addSecretInput("bar1"); + terminal.addSecretInput("bar2"); + terminal.addSecretInput("bar3"); execute(randomFrom("-x", "--stdin"), "foo1", "foo2", "foo3"); assertSecureString("foo1", "bar1", password); assertSecureString("foo2", "bar2", password); @@ -228,7 +220,7 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { for (int i = 0; i < stringSize; i++) { secretChars.write((char) randomIntBetween(129, 2048)); } - setInput(secretChars.toString()); + terminal.addSecretInput(secretChars.toString()); execute("-x", "foo"); assertSecureString("foo", secretChars.toString(), password); } @@ -265,8 +257,4 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { execute("foo"); assertSecureString("foo", "bar", password); } - - void setInput(String inputStr) { - input = new ByteArrayInputStream(inputStr.getBytes(StandardCharsets.UTF_8)); - } } diff --git a/docs/changelog/126729.yaml b/docs/changelog/126729.yaml new file mode 100644 index 000000000000..0a5e296e4c25 --- /dev/null +++ b/docs/changelog/126729.yaml @@ -0,0 +1,6 @@ +pr: 126729 +summary: Use terminal reader in keystore add command +area: Infra/CLI +type: bug +issues: + - 98115