Skip to content

Commit b0be180

Browse files
Password Protected Keystore (Feature Branch) (cleaned up) (#49268)
* Reload secure settings with password (#43197) If a password is not set, we assume an empty string to be compatible with previous behavior. Only allow the reload to be broadcast to other nodes if TLS is enabled for the transport layer. * Add passphrase support to elasticsearch-keystore (#38498) This change adds support for keystore passphrases to all subcommands of the elasticsearch-keystore cli tool and adds a subcommand for changing the passphrase of an existing keystore. The work to read the passphrase in Elasticsearch when loading, which will be addressed in a different PR. Subcommands of elasticsearch-keystore can handle (open and create) passphrase protected keystores When reading a keystore, a user is only prompted for a passphrase only if the keystore is passphrase protected. When creating a keystore, a user is allowed (default behavior) to create one with an empty passphrase Passphrase can be set to be empty when changing/setting it for an existing keystore Relates to: #32691 Supersedes: #37472 * Restore behavior for force parameter (#44847) Turns out that the behavior of `-f` for the add and add-file sub commands where it would also forcibly create the keystore if it didn't exist, was by design - although undocumented. This change restores that behavior auto-creating a keystore that is not password protected if the force flag is used. The force OptionSpec is moved to the BaseKeyStoreCommand as we will presumably want to maintain the same behavior in any other command that takes a force option. * Handle pwd protected keystores in all CLI tools (#45289) This change ensures that `elasticsearch-setup-passwords` and `elasticsearch-saml-metadata` can handle a password protected elasticsearch.keystore. For setup passwords the user would be prompted to add the elasticsearch keystore password upon running the tool. There is no option to pass the password as a parameter as we assume the user is present in order to enter the desired passwords for the built-in users. For saml-metadata, we prompt for the keystore password at all times even though we'd only need to read something from the keystore when there is a signing or encryption configuration. * Modify docs for setup passwords and saml metadata cli (#45797) Adds a sentence in the documentation of `elasticsearch-setup-passwords` and `elasticsearch-saml-metadata` to describe that users would be prompted for the keystore's password when running these CLI tools, when the keystore is password protected. Co-Authored-By: Lisa Cawley <[email protected]> * Elasticsearch keystore passphrase for startup scripts (#44775) This commit allows a user to provide a keystore password on Elasticsearch startup, but only prompts when the keystore exists and is encrypted. The entrypoint in Java code is standard input. When the Bootstrap class is checking for secure keystore settings, it checks whether or not the keystore is encrypted. If so, we read one line from standard input and use this as the password. For simplicity's sake, we allow a maximum passphrase length of 128 characters. (This is an arbitrary limit and could be increased or eliminated. It is also enforced in the keystore tools, so that a user can't create a password that's too long to enter at startup.) In order to provide a password on standard input, we have to account for four different ways of starting Elasticsearch: the bash startup script, the Windows batch startup script, systemd startup, and docker startup. We use wrapper scripts to reduce systemd and docker to the bash case: in both cases, a wrapper script can read a passphrase from the filesystem and pass it to the bash script. In order to simplify testing the need for a passphrase, I have added a has-passwd command to the keystore tool. This command can run silently, and exit with status 0 when the keystore has a password. It exits with status 1 if the keystore doesn't exist or exists and is unencrypted. A good deal of the code-change in this commit has to do with refactoring packaging tests to cleanly use the same tests for both the "archive" and the "package" cases. This required not only moving tests around, but also adding some convenience methods for an abstraction layer over distribution-specific commands. I will write some user-facing documentation for these changes in a follow-up commit. * Adjust docs for password protected keystore (#45054) This commit adds relevant parts in the elasticsearch-keystore sub-commands reference docs and in the reload secure settings API doc. * Cleanup after feature branch reconstruction The feature branch for the password-protected keystore, due to an accident, contains a large number of unrelated commits. In order to get a cleaner merge, I've cherry-picked the main commits that went into the feature branch against a branch derived from master — essentially, a rebase onto master. We've ignored some tests that will addressed in follow-up PRs to the feature branch.
1 parent 64e1a77 commit b0be180

File tree

71 files changed

+2320
-543
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2320
-543
lines changed

Vagrantfile

+1
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ JAVA
475475
ensure curl
476476
ensure unzip
477477
ensure rsync
478+
ensure expect
478479
479480
installed bats || {
480481
# Bats lives in a git repository....

build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ task verifyVersions {
205205
* after the backport of the backcompat code is complete.
206206
*/
207207

208-
boolean bwc_tests_enabled = true
209-
final String bwc_tests_disabled_issue = "" /* place a PR link here when committing bwc changes */
208+
boolean bwc_tests_enabled = false
209+
final String bwc_tests_disabled_issue = "https://github.com/elastic/elasticsearch/pull/43197"
210210
if (bwc_tests_enabled == false) {
211211
if (bwc_tests_disabled_issue.isEmpty()) {
212212
throw new GradleException("bwc_tests_disabled_issue must be set when bwc_tests_enabled == false")

distribution/docker/docker-test-entrypoint.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/bash
22
cd /usr/share/elasticsearch/bin/
3-
./elasticsearch-users useradd x_pack_rest_user -p x-pack-test-password -r superuser || true
3+
./elasticsearch-users useradd x_pack_rest_user -p x-pack-test-password -r superuser || true
44
echo "testnode" > /tmp/password
55
cat /tmp/password | ./elasticsearch-keystore add -x -f -v 'xpack.security.transport.ssl.keystore.secure_password'
66
cat /tmp/password | ./elasticsearch-keystore add -x -f -v 'xpack.security.http.ssl.keystore.secure_password'

distribution/docker/src/docker/bin/docker-entrypoint.sh

+13-3
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,18 @@ if [[ -f bin/elasticsearch-users ]]; then
117117
# honor the variable if it's present.
118118
if [[ -n "$ELASTIC_PASSWORD" ]]; then
119119
[[ -f /usr/share/elasticsearch/config/elasticsearch.keystore ]] || (run_as_other_user_if_needed elasticsearch-keystore create)
120-
if ! (run_as_other_user_if_needed elasticsearch-keystore list | grep -q '^bootstrap.password$'); then
121-
(run_as_other_user_if_needed echo "$ELASTIC_PASSWORD" | elasticsearch-keystore add -x 'bootstrap.password')
120+
if ! (run_as_other_user_if_needed elasticsearch-keystore has-passwd --silent) ; then
121+
# keystore is unencrypted
122+
if ! (run_as_other_user_if_needed elasticsearch-keystore list | grep -q '^bootstrap.password$'); then
123+
(run_as_other_user_if_needed echo "$ELASTIC_PASSWORD" | elasticsearch-keystore add -x 'bootstrap.password')
124+
fi
125+
else
126+
# keystore requires password
127+
if ! (run_as_other_user_if_needed echo "$KEYSTORE_PASSWORD" \
128+
| elasticsearch-keystore list | grep -q '^bootstrap.password$') ; then
129+
COMMANDS="$(printf "%s\n%s" "$KEYSTORE_PASSWORD" "$ELASTIC_PASSWORD")"
130+
(run_as_other_user_if_needed echo "$COMMANDS" | elasticsearch-keystore add -x 'bootstrap.password')
131+
fi
122132
fi
123133
fi
124134
fi
@@ -130,4 +140,4 @@ if [[ "$(id -u)" == "0" ]]; then
130140
fi
131141
fi
132142

133-
run_as_other_user_if_needed /usr/share/elasticsearch/bin/elasticsearch "${es_opts[@]}"
143+
run_as_other_user_if_needed /usr/share/elasticsearch/bin/elasticsearch "${es_opts[@]}" <<<"$KEYSTORE_PASSWORD"

distribution/packages/build.gradle

+4
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ Closure commonPackageConfig(String type, boolean oss, boolean jdk) {
231231
from "${packagingFiles}/systemd/sysctl/elasticsearch.conf"
232232
fileMode 0644
233233
}
234+
into('/usr/share/elasticsearch/bin') {
235+
from "${packagingFiles}/systemd/systemd-entrypoint"
236+
fileMode 0755
237+
}
234238

235239
// ========= sysV init =========
236240
configurationFile '/etc/init.d/elasticsearch'

distribution/packages/src/common/scripts/posttrans

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ if [ ! -f /etc/elasticsearch/elasticsearch.keystore ]; then
44
chmod 660 /etc/elasticsearch/elasticsearch.keystore
55
md5sum /etc/elasticsearch/elasticsearch.keystore > /etc/elasticsearch/.elasticsearch.keystore.initial_md5sum
66
else
7-
/usr/share/elasticsearch/bin/elasticsearch-keystore upgrade
7+
if /usr/share/elasticsearch/bin/elasticsearch-keystore has-passwd --silent ; then
8+
echo "### Warning: unable to upgrade encrypted keystore" 1>&2
9+
echo " Please run elasticsearch-keystore upgrade and enter password" 1>&2
10+
else
11+
/usr/share/elasticsearch/bin/elasticsearch-keystore upgrade
12+
fi
813
fi
914

1015
${scripts.footer}

distribution/packages/src/common/systemd/elasticsearch.service

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ WorkingDirectory=/usr/share/elasticsearch
1919
User=elasticsearch
2020
Group=elasticsearch
2121

22-
ExecStart=/usr/share/elasticsearch/bin/elasticsearch -p ${PID_DIR}/elasticsearch.pid --quiet
22+
ExecStart=/usr/share/elasticsearch/bin/systemd-entrypoint -p ${PID_DIR}/elasticsearch.pid --quiet
2323

2424
# StandardOutput is configured to redirect to journalctl since
2525
# some error messages may be logged in standard output before
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/sh
2+
3+
# This wrapper script allows SystemD to feed a file containing a passphrase into
4+
# the main Elasticsearch startup script
5+
6+
if [ -n "$ES_KEYSTORE_PASSPHRASE_FILE" ] ; then
7+
exec /usr/share/elasticsearch/bin/elasticsearch "$@" < "$ES_KEYSTORE_PASSPHRASE_FILE"
8+
else
9+
exec /usr/share/elasticsearch/bin/elasticsearch "$@"
10+
fi

distribution/src/bin/elasticsearch

+15-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ if [ -z "$ES_TMPDIR" ]; then
2020
ES_TMPDIR=`"$JAVA" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.TempDirectory`
2121
fi
2222

23+
# get keystore password before setting java options to avoid
24+
# conflicting GC configurations for the keystore tools
25+
unset KEYSTORE_PASSWORD
26+
KEYSTORE_PASSWORD=
27+
if ! echo $* | grep -E -q '(^-h |-h$| -h |--help$|--help |^-V |-V$| -V |--version$|--version )' \
28+
&& "`dirname "$0"`"/elasticsearch-keystore has-passwd --silent
29+
then
30+
if ! read -s -r -p "Elasticsearch keystore password: " KEYSTORE_PASSWORD ; then
31+
echo "Failed to read keystore password on console" 1>&2
32+
exit 1
33+
fi
34+
fi
35+
2336
ES_JVM_OPTIONS="$ES_PATH_CONF"/jvm.options
2437
ES_JAVA_OPTS=`export ES_TMPDIR; "$JAVA" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.JvmOptionsParser "$ES_JVM_OPTIONS"`
2538

@@ -35,7 +48,7 @@ if ! echo $* | grep -E '(^-d |-d$| -d |--daemonize$|--daemonize )' > /dev/null;
3548
-Des.bundled_jdk="$ES_BUNDLED_JDK" \
3649
-cp "$ES_CLASSPATH" \
3750
org.elasticsearch.bootstrap.Elasticsearch \
38-
"$@"
51+
"$@" <<<"$KEYSTORE_PASSWORD"
3952
else
4053
exec \
4154
"$JAVA" \
@@ -48,7 +61,7 @@ else
4861
-cp "$ES_CLASSPATH" \
4962
org.elasticsearch.bootstrap.Elasticsearch \
5063
"$@" \
51-
<&- &
64+
<<<"$KEYSTORE_PASSWORD" &
5265
retval=$?
5366
pid=$!
5467
[ $retval -eq 0 ] || exit $retval

distribution/src/bin/elasticsearch-cli.bat

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ set ES_JAVA_OPTS=-Xms4m -Xmx64m -XX:+UseSerialGC %ES_JAVA_OPTS%
2525
-cp "%ES_CLASSPATH%" ^
2626
"%ES_MAIN_CLASS%" ^
2727
%*
28-
28+
2929
exit /b %ERRORLEVEL%

distribution/src/bin/elasticsearch.bat

+41-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ setlocal enabledelayedexpansion
44
setlocal enableextensions
55

66
SET params='%*'
7+
SET checkpassword=Y
78

89
:loop
910
FOR /F "usebackq tokens=1* delims= " %%A IN (!params!) DO (
@@ -18,6 +19,20 @@ FOR /F "usebackq tokens=1* delims= " %%A IN (!params!) DO (
1819
SET silent=Y
1920
)
2021

22+
IF "!current!" == "-h" (
23+
SET checkpassword=N
24+
)
25+
IF "!current!" == "--help" (
26+
SET checkpassword=N
27+
)
28+
29+
IF "!current!" == "-V" (
30+
SET checkpassword=N
31+
)
32+
IF "!current!" == "--version" (
33+
SET checkpassword=N
34+
)
35+
2136
IF "!silent!" == "Y" (
2237
SET nopauseonerror=Y
2338
) ELSE (
@@ -41,6 +56,18 @@ IF ERRORLEVEL 1 (
4156
EXIT /B %ERRORLEVEL%
4257
)
4358

59+
SET KEYSTORE_PASSWORD=
60+
IF "%checkpassword%"=="Y" (
61+
CALL "%~dp0elasticsearch-keystore.bat" has-passwd --silent
62+
IF !ERRORLEVEL! EQU 0 (
63+
SET /P KEYSTORE_PASSWORD=Elasticsearch keystore password:
64+
IF !ERRORLEVEL! NEQ 0 (
65+
ECHO Failed to read keystore password on standard input
66+
EXIT /B !ERRORLEVEL!
67+
)
68+
)
69+
)
70+
4471
if not defined ES_TMPDIR (
4572
for /f "tokens=* usebackq" %%a in (`CALL %JAVA% -cp "!ES_CLASSPATH!" "org.elasticsearch.tools.launchers.TempDirectory"`) do set ES_TMPDIR=%%a
4673
)
@@ -54,7 +81,20 @@ if "%MAYBE_JVM_OPTIONS_PARSER_FAILED%" == "jvm_options_parser_failed" (
5481
exit /b 1
5582
)
5683

57-
%JAVA% %ES_JAVA_OPTS% -Delasticsearch -Des.path.home="%ES_HOME%" -Des.path.conf="%ES_PATH_CONF%" -Des.distribution.flavor="%ES_DISTRIBUTION_FLAVOR%" -Des.distribution.type="%ES_DISTRIBUTION_TYPE%" -Des.bundled_jdk="%ES_BUNDLED_JDK%" -cp "%ES_CLASSPATH%" "org.elasticsearch.bootstrap.Elasticsearch" !newparams!
84+
rem windows batch pipe will choke on special characters in strings
85+
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^^=^^^^!
86+
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^&=^^^&!
87+
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^|=^^^|!
88+
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^<=^^^<!
89+
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^>=^^^>!
90+
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^\=^^^\!
91+
92+
ECHO.!KEYSTORE_PASSWORD!| %JAVA% %ES_JAVA_OPTS% -Delasticsearch ^
93+
-Des.path.home="%ES_HOME%" -Des.path.conf="%ES_PATH_CONF%" ^
94+
-Des.distribution.flavor="%ES_DISTRIBUTION_FLAVOR%" ^
95+
-Des.distribution.type="%ES_DISTRIBUTION_TYPE%" ^
96+
-Des.bundled_jdk="%ES_BUNDLED_JDK%" ^
97+
-cp "%ES_CLASSPATH%" "org.elasticsearch.bootstrap.Elasticsearch" !newparams!
5898

5999
endlocal
60100
endlocal

distribution/tools/keystore-cli/src/main/java/org/elasticsearch/common/settings/AddFileKeyStoreCommand.java

+10-24
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
import joptsimple.OptionSet;
2828
import joptsimple.OptionSpec;
29-
import org.elasticsearch.cli.EnvironmentAwareCommand;
3029
import org.elasticsearch.cli.ExitCodes;
3130
import org.elasticsearch.cli.Terminal;
3231
import org.elasticsearch.cli.UserException;
@@ -37,42 +36,29 @@
3736
/**
3837
* A subcommand for the keystore cli which adds a file setting.
3938
*/
40-
class AddFileKeyStoreCommand extends EnvironmentAwareCommand {
39+
class AddFileKeyStoreCommand extends BaseKeyStoreCommand {
4140

42-
private final OptionSpec<Void> forceOption;
4341
private final OptionSpec<String> arguments;
4442

4543
AddFileKeyStoreCommand() {
46-
super("Add a file setting to the keystore");
47-
this.forceOption = parser.acceptsAll(Arrays.asList("f", "force"), "Overwrite existing setting without prompting");
44+
super("Add a file setting to the keystore", false);
45+
this.forceOption = parser.acceptsAll(Arrays.asList("f", "force"),
46+
"Overwrite existing setting without prompting, creating keystore if necessary");
4847
// jopt simple has issue with multiple non options, so we just get one set of them here
4948
// and convert to File when necessary
5049
// see https://github.com/jopt-simple/jopt-simple/issues/103
5150
this.arguments = parser.nonOptions("setting [filepath]");
5251
}
5352

5453
@Override
55-
protected void execute(Terminal terminal, OptionSet options, Environment env) throws Exception {
56-
KeyStoreWrapper keystore = KeyStoreWrapper.load(env.configFile());
57-
if (keystore == null) {
58-
if (options.has(forceOption) == false &&
59-
terminal.promptYesNo("The elasticsearch keystore does not exist. Do you want to create it?", false) == false) {
60-
terminal.println("Exiting without creating keystore.");
61-
return;
62-
}
63-
keystore = KeyStoreWrapper.create();
64-
keystore.save(env.configFile(), new char[0] /* always use empty passphrase for auto created keystore */);
65-
terminal.println("Created elasticsearch keystore in " + env.configFile());
66-
} else {
67-
keystore.decrypt(new char[0] /* TODO: prompt for password when they are supported */);
68-
}
69-
54+
protected void executeCommand(Terminal terminal, OptionSet options, Environment env) throws Exception {
7055
List<String> argumentValues = arguments.values(options);
7156
if (argumentValues.size() == 0) {
7257
throw new UserException(ExitCodes.USAGE, "Missing setting name");
7358
}
7459
String setting = argumentValues.get(0);
75-
if (keystore.getSettingNames().contains(setting) && options.has(forceOption) == false) {
60+
final KeyStoreWrapper keyStore = getKeyStore();
61+
if (keyStore.getSettingNames().contains(setting) && options.has(forceOption) == false) {
7662
if (terminal.promptYesNo("Setting " + setting + " already exists. Overwrite?", false) == false) {
7763
terminal.println("Exiting without modifying keystore.");
7864
return;
@@ -90,11 +76,11 @@ protected void execute(Terminal terminal, OptionSet options, Environment env) th
9076
throw new UserException(ExitCodes.USAGE, "Unrecognized extra arguments [" +
9177
String.join(", ", argumentValues.subList(2, argumentValues.size())) + "] after filepath");
9278
}
93-
keystore.setFile(setting, Files.readAllBytes(file));
94-
keystore.save(env.configFile(), new char[0]);
79+
keyStore.setFile(setting, Files.readAllBytes(file));
80+
keyStore.save(env.configFile(), getKeyStorePassword().getChars());
9581
}
9682

97-
@SuppressForbidden(reason="file arg for cli")
83+
@SuppressForbidden(reason = "file arg for cli")
9884
private Path getPath(String file) {
9985
return PathUtils.get(file);
10086
}

distribution/tools/keystore-cli/src/main/java/org/elasticsearch/common/settings/AddStringKeyStoreCommand.java

+13-36
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@
2020
package org.elasticsearch.common.settings;
2121

2222
import java.io.BufferedReader;
23-
import java.io.CharArrayWriter;
2423
import java.io.InputStream;
2524
import java.io.InputStreamReader;
2625
import java.nio.charset.StandardCharsets;
2726
import java.util.Arrays;
2827

2928
import joptsimple.OptionSet;
3029
import joptsimple.OptionSpec;
31-
import org.elasticsearch.cli.EnvironmentAwareCommand;
3230
import org.elasticsearch.cli.ExitCodes;
3331
import org.elasticsearch.cli.Terminal;
3432
import org.elasticsearch.cli.UserException;
@@ -37,16 +35,16 @@
3735
/**
3836
* A subcommand for the keystore cli which adds a string setting.
3937
*/
40-
class AddStringKeyStoreCommand extends EnvironmentAwareCommand {
38+
class AddStringKeyStoreCommand extends BaseKeyStoreCommand {
4139

4240
private final OptionSpec<Void> stdinOption;
43-
private final OptionSpec<Void> forceOption;
4441
private final OptionSpec<String> arguments;
4542

4643
AddStringKeyStoreCommand() {
47-
super("Add a string setting to the keystore");
44+
super("Add a string setting to the keystore", false);
4845
this.stdinOption = parser.acceptsAll(Arrays.asList("x", "stdin"), "Read setting value from stdin");
49-
this.forceOption = parser.acceptsAll(Arrays.asList("f", "force"), "Overwrite existing setting without prompting");
46+
this.forceOption = parser.acceptsAll(Arrays.asList("f", "force"),
47+
"Overwrite existing setting without prompting, creating keystore if necessary");
5048
this.arguments = parser.nonOptions("setting name");
5149
}
5250

@@ -56,26 +54,13 @@ InputStream getStdin() {
5654
}
5755

5856
@Override
59-
protected void execute(Terminal terminal, OptionSet options, Environment env) throws Exception {
60-
KeyStoreWrapper keystore = KeyStoreWrapper.load(env.configFile());
61-
if (keystore == null) {
62-
if (options.has(forceOption) == false &&
63-
terminal.promptYesNo("The elasticsearch keystore does not exist. Do you want to create it?", false) == false) {
64-
terminal.println("Exiting without creating keystore.");
65-
return;
66-
}
67-
keystore = KeyStoreWrapper.create();
68-
keystore.save(env.configFile(), new char[0] /* always use empty passphrase for auto created keystore */);
69-
terminal.println("Created elasticsearch keystore in " + env.configFile());
70-
} else {
71-
keystore.decrypt(new char[0] /* TODO: prompt for password when they are supported */);
72-
}
73-
57+
protected void executeCommand(Terminal terminal, OptionSet options, Environment env) throws Exception {
7458
String setting = arguments.value(options);
7559
if (setting == null) {
7660
throw new UserException(ExitCodes.USAGE, "The setting name can not be null");
7761
}
78-
if (keystore.getSettingNames().contains(setting) && options.has(forceOption) == false) {
62+
final KeyStoreWrapper keyStore = getKeyStore();
63+
if (keyStore.getSettingNames().contains(setting) && options.has(forceOption) == false) {
7964
if (terminal.promptYesNo("Setting " + setting + " already exists. Overwrite?", false) == false) {
8065
terminal.println("Exiting without modifying keystore.");
8166
return;
@@ -84,26 +69,18 @@ protected void execute(Terminal terminal, OptionSet options, Environment env) th
8469

8570
final char[] value;
8671
if (options.has(stdinOption)) {
87-
try (BufferedReader stdinReader = new BufferedReader(new InputStreamReader(getStdin(), StandardCharsets.UTF_8));
88-
CharArrayWriter writer = new CharArrayWriter()) {
89-
int charInt;
90-
while ((charInt = stdinReader.read()) != -1) {
91-
if ((char) charInt == '\r' || (char) charInt == '\n') {
92-
break;
93-
}
94-
writer.write((char) charInt);
95-
}
96-
value = writer.toCharArray();
97-
}
72+
BufferedReader stdinReader = new BufferedReader(new InputStreamReader(getStdin(), StandardCharsets.UTF_8));
73+
value = stdinReader.readLine().toCharArray();
9874
} else {
9975
value = terminal.readSecret("Enter value for " + setting + ": ");
10076
}
10177

10278
try {
103-
keystore.setString(setting, value);
104-
} catch (final IllegalArgumentException e) {
79+
keyStore.setString(setting, value);
80+
} catch (IllegalArgumentException e) {
10581
throw new UserException(ExitCodes.DATA_ERROR, e.getMessage());
10682
}
107-
keystore.save(env.configFile(), new char[0]);
83+
keyStore.save(env.configFile(), getKeyStorePassword().getChars());
84+
10885
}
10986
}

0 commit comments

Comments
 (0)