Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elasticsearch keystore passphrase for startup scripts #44775

Merged
Show file tree
Hide file tree
Changes from 119 commits
Commits
Show all changes
122 commits
Select commit Hold shift + click to select a range
c58f3aa
Add passphrase support to elasticsearch-keystore
jkakavas Jan 15, 2019
c74685f
Address feedback
jkakavas Jan 23, 2019
af3d5e9
Allow creating obfuscated keystores without prompting for a passphrase
jkakavas Jan 23, 2019
d118da4
Create obfuscated keystores for integTestCluster tasks. This can be p…
jkakavas Jan 23, 2019
041143e
Merge remote-tracking branch 'origin/master' into elasticsearch-keyst…
jkakavas Jan 23, 2019
852533a
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
jkakavas Feb 6, 2019
668c438
address feedback
jkakavas Feb 6, 2019
95e1a78
Handle tests by creating obfuscated keystores by default - At least u…
jkakavas Feb 6, 2019
bc5b99d
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
jkakavas Feb 6, 2019
f095d90
Merge remote-tracking branch 'origin/feature-pwd-protected-keystore' …
jkakavas Jun 14, 2019
76ea066
fix checkstyl
jkakavas Jun 14, 2019
3bf1830
Address feedback
jkakavas Jun 14, 2019
500c79a
Merge remote-tracking branch 'origin/feature-pwd-protected-keystore' …
jkakavas Jun 27, 2019
ba4a9ba
revert unnecessary formatting changes
jkakavas Jun 27, 2019
2b74f64
remove nopass again
jkakavas Jun 27, 2019
ecc0ed6
Addresses feedback
jkakavas Jun 28, 2019
ac5cf83
Merge remote-tracking branch 'origin/feature-pwd-protected-keystore' …
jkakavas Jun 30, 2019
ca55074
address feedback
jkakavas Jul 9, 2019
690df96
Merge remote-tracking branch 'origin/feature-pwd-protected-keystore' …
jkakavas Jul 9, 2019
250c9f2
Read keystore password from stdin on startup
williamrandolph Jun 24, 2019
a167d5c
Add thread safety and fix typos
williamrandolph Jun 24, 2019
e390afe
Remove command line flag for standard input
williamrandolph Jun 27, 2019
8c99702
Let bin/elasticsearch read passwd from FIFO/file
williamrandolph Jul 1, 2019
ef66eaf
Improve bin/elasticsearch portability
williamrandolph Jul 3, 2019
6a2ecc5
Avoid multiple buffered readers of standard input
williamrandolph Jul 10, 2019
85c9160
Avoid forbidden and restricted APIs
williamrandolph Jul 11, 2019
3d11327
Add keystore passphrase support to docker images
williamrandolph Jul 11, 2019
9ab6cdf
Merge branch 'elasticsearch-keystore-cli-passphrase' into elasticsear…
williamrandolph Jul 12, 2019
c9c0b42
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Jul 23, 2019
193ff6e
Send all input via the terminal in tests
williamrandolph Jul 23, 2019
54de1eb
Remove some unused imports
williamrandolph Jul 24, 2019
636ac69
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Jul 30, 2019
e581b55
Back out OSX delay workaround
williamrandolph Jul 30, 2019
c0b1fc2
Address PR feedback
williamrandolph Jul 30, 2019
e1f50b6
Discard standard input in cluster integration tests
williamrandolph Jul 30, 2019
30ce2a2
Close stdin to elasticsearch process
williamrandolph Jul 30, 2019
ef8a6c4
Add a write to stdin for restclusters
williamrandolph Jul 30, 2019
eb32c60
Check that keystore command can be executed
williamrandolph Jul 31, 2019
9fb0a52
Remove unused imports
williamrandolph Jul 31, 2019
52305c0
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Jul 31, 2019
a66994a
Adjust bin/elasticsearch for running in docker
williamrandolph Aug 1, 2019
a44fc58
RPM Packaging Tests for Keystore
williamrandolph Aug 6, 2019
97ddb4e
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Aug 6, 2019
1d22a27
Remove extra keystore test
williamrandolph Aug 7, 2019
17aa6d5
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Aug 7, 2019
94b98e7
Add integration tests for archives
williamrandolph Aug 7, 2019
e227ce2
Update new vagrant tests to run on Windows
williamrandolph Aug 13, 2019
c1e4008
Simplify code to set keystore password in test
williamrandolph Aug 13, 2019
3bd969a
Merging feature branch into PR branch
williamrandolph Aug 16, 2019
7a7739a
Remove FIFO checks from bin/elasticsearch
williamrandolph Aug 22, 2019
8e5d02e
Assume password on stdin when bootstrapping
williamrandolph Aug 22, 2019
775c35c
Clean up terminal interfaces and tests
williamrandolph Aug 22, 2019
3b0fd80
Checkstyle - remove unused imports
williamrandolph Aug 23, 2019
d693a44
Create new has-passwd keystore CLI subcommand
williamrandolph Aug 23, 2019
7d98e3d
Revert unused addition to CommandTestCase
williamrandolph Aug 23, 2019
425c6c5
Add license headers to new files
williamrandolph Aug 23, 2019
bef250b
Reorder clauses for clarity
williamrandolph Aug 23, 2019
5896f31
merge feature branch into PR branch
williamrandolph Aug 23, 2019
7de60e9
Restore import dropped during merge
williamrandolph Aug 23, 2019
155464a
Move keystore tests into a single test class
williamrandolph Aug 23, 2019
60a9f0b
Adapt keystore management tests for RPMs
williamrandolph Aug 26, 2019
1e26b2f
Refactor keystore os tests for clarity
williamrandolph Aug 26, 2019
dc1f312
Checkstyle: remove unused import
williamrandolph Aug 27, 2019
d7ce46e
Add license header to keystore test
williamrandolph Aug 27, 2019
c3e6795
Improvements to vagrant tests
williamrandolph Aug 29, 2019
f108fa3
Get Windows tests to pass
williamrandolph Aug 31, 2019
0cfa719
Undo changes having to do with string encoding
williamrandolph Sep 1, 2019
a613b45
Add TTY-based tests for non-Windows archives
williamrandolph Sep 2, 2019
6b090a6
Rename test for accuracy
williamrandolph Sep 2, 2019
3f79421
Remove unneeded changes to clean up diff
williamrandolph Sep 2, 2019
c4868ff
Revert unneeded changes to windows batch scripts
williamrandolph Sep 4, 2019
1e1e459
Remove unneeded whitespace change
williamrandolph Sep 4, 2019
9e6f767
One more whitespace tweak
williamrandolph Sep 4, 2019
5585c61
Use delayed expansion variable for Windows pwd
williamrandolph Sep 6, 2019
2c69dba
Respond to PR feedback
williamrandolph Sep 6, 2019
c97749a
Fix BufferedReader usage
williamrandolph Sep 6, 2019
e06da98
Improve os tests
williamrandolph Sep 6, 2019
1436534
Escape special characters in password for windows
williamrandolph Sep 6, 2019
a1a125b
Remove obsolete comment
williamrandolph Sep 6, 2019
d5a04a7
Handle backslashes in bash keystore passwords
williamrandolph Sep 7, 2019
cb61eb7
Give elasticsearch-keystore a true silent mode
williamrandolph Sep 9, 2019
4611d54
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Sep 9, 2019
19442c8
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Sep 19, 2019
c9a6e63
Use shell env vars rather than writing to env file
williamrandolph Sep 19, 2019
6b760b2
Remove redundant non-special-char tests
williamrandolph Sep 19, 2019
d47e1fe
Test for specific password failure message
williamrandolph Sep 26, 2019
87ecea4
Avoid intermediate Strings when reading secrets
williamrandolph Oct 2, 2019
34e431f
Merging upstream changes from feature branch
williamrandolph Oct 2, 2019
13c27f3
Specify InputStream encoding in tests
williamrandolph Oct 2, 2019
1501bf3
Remove exit message override
williamrandolph Oct 2, 2019
2273b11
Use Conditional pattern for packages and archives
williamrandolph Oct 3, 2019
0982d04
Use keystore passphrase file only with systemd
williamrandolph Oct 4, 2019
7146b36
Add a information to assertion failure message
williamrandolph Oct 4, 2019
7a65f22
Clear out stray keystore files between tests groups
williamrandolph Oct 4, 2019
67fa0f8
Unset systemd environment variables after use
williamrandolph Oct 4, 2019
b0e3a4b
Move entrypoint to an ok location for dpkg
williamrandolph Oct 5, 2019
3883d59
Rename systemd entrypoint script
williamrandolph Oct 7, 2019
0c0a56a
Use null message to suppress error output for CLI
williamrandolph Oct 7, 2019
945aead
Cleanup static import references
williamrandolph Oct 7, 2019
026ee0d
Improve error message
williamrandolph Oct 7, 2019
f271e59
Re-work methods for reading from standard input
williamrandolph Oct 7, 2019
43ce860
Remove custom buffer limit for BufferedReader
williamrandolph Oct 7, 2019
16bc6be
Update comment to match code
williamrandolph Oct 7, 2019
1855bce
Use static import for static methods
williamrandolph Oct 7, 2019
43ed544
Rename log files between tests
williamrandolph Oct 9, 2019
b7c2d66
Merge changes from master
williamrandolph Oct 10, 2019
2725769
Add some docker support after merge
williamrandolph Oct 10, 2019
44bfb95
Add sleep time to daemonized ES startup in qa test
williamrandolph Oct 10, 2019
457fc59
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Oct 15, 2019
ef850d2
Set file permissions for Windows keystore tests
williamrandolph Oct 15, 2019
e548d55
Run chown on autocreated keystore on Windows tests
williamrandolph Oct 15, 2019
7eb26c2
Simplify tests with StringReader
williamrandolph Oct 16, 2019
36d61ae
Clarify purpose of unit test
williamrandolph Oct 16, 2019
6fc4994
Sundry trivial cleanup
williamrandolph Oct 16, 2019
94e6a3f
Refactor big Powershell script string
williamrandolph Oct 16, 2019
1ef3dfb
Get powershell output path via static method
williamrandolph Oct 16, 2019
c31c88e
Checkstyle - remove unused import
williamrandolph Oct 16, 2019
6eb3e35
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Oct 16, 2019
b85eed9
Merge branch 'feature-pwd-protected-keystore' into elasticsearch-keys…
williamrandolph Oct 24, 2019
56b83f1
Use expectThrows instead of JUnit rule
williamrandolph Oct 28, 2019
f982f91
Bootstrap's readPassphrase delegates to Terminal
williamrandolph Oct 28, 2019
73e35e7
Remove unused imports
williamrandolph Oct 28, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ JAVA
ensure curl
ensure unzip
ensure rsync
ensure expect

installed bats || {
# Bats lives in a git repository....
Expand Down
16 changes: 13 additions & 3 deletions distribution/docker/src/docker/bin/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,18 @@ if [[ -f bin/elasticsearch-users ]]; then
# honor the variable if it's present.
if [[ -n "$ELASTIC_PASSWORD" ]]; then
[[ -f /usr/share/elasticsearch/config/elasticsearch.keystore ]] || (run_as_other_user_if_needed elasticsearch-keystore create)
if ! (run_as_other_user_if_needed elasticsearch-keystore list | grep -q '^bootstrap.password$'); then
(run_as_other_user_if_needed echo "$ELASTIC_PASSWORD" | elasticsearch-keystore add -x 'bootstrap.password')
if ! (run_as_other_user_if_needed elasticsearch-keystore has-passwd --silent) ; then
# keystore is unencrypted
if ! (run_as_other_user_if_needed elasticsearch-keystore list | grep -q '^bootstrap.password$'); then
(run_as_other_user_if_needed echo "$ELASTIC_PASSWORD" | elasticsearch-keystore add -x 'bootstrap.password')
fi
else
# keystore requires password
if ! (run_as_other_user_if_needed echo "$KEYSTORE_PASSWORD" \
| elasticsearch-keystore list | grep -q '^bootstrap.password$') ; then
COMMANDS="$(printf "%s\n%s" "$KEYSTORE_PASSWORD" "$ELASTIC_PASSWORD")"
(run_as_other_user_if_needed echo "$COMMANDS" | elasticsearch-keystore add -x 'bootstrap.password')
fi
fi
fi
fi
Expand All @@ -97,4 +107,4 @@ if [[ "$(id -u)" == "0" ]]; then
fi
fi

run_as_other_user_if_needed /usr/share/elasticsearch/bin/elasticsearch "${es_opts[@]}"
run_as_other_user_if_needed /usr/share/elasticsearch/bin/elasticsearch "${es_opts[@]}" <<<"$KEYSTORE_PASSWORD"
4 changes: 4 additions & 0 deletions distribution/packages/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ Closure commonPackageConfig(String type, boolean oss, boolean jdk) {
from "${packagingFiles}/systemd/sysctl/elasticsearch.conf"
fileMode 0644
}
into('/usr/share/elasticsearch/bin') {
from "${packagingFiles}/systemd/systemd-entrypoint"
fileMode 0755
}

// ========= sysV init =========
configurationFile '/etc/init.d/elasticsearch'
Expand Down
7 changes: 6 additions & 1 deletion distribution/packages/src/common/scripts/posttrans
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ if [ ! -f /etc/elasticsearch/elasticsearch.keystore ]; then
chmod 660 /etc/elasticsearch/elasticsearch.keystore
md5sum /etc/elasticsearch/elasticsearch.keystore > /etc/elasticsearch/.elasticsearch.keystore.initial_md5sum
else
/usr/share/elasticsearch/bin/elasticsearch-keystore upgrade
if /usr/share/elasticsearch/bin/elasticsearch-keystore has-passwd --silent ; then
echo "### Warning: unable to upgrade encrypted keystore" 1>&2
echo " Please run elasticsearch-keystore upgrade and enter password" 1>&2
else
/usr/share/elasticsearch/bin/elasticsearch-keystore upgrade
fi
fi

${scripts.footer}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ WorkingDirectory=/usr/share/elasticsearch
User=elasticsearch
Group=elasticsearch

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

# StandardOutput is configured to redirect to journalctl since
# some error messages may be logged in standard output before
Expand Down
10 changes: 10 additions & 0 deletions distribution/packages/src/common/systemd/systemd-entrypoint
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh

# This wrapper script allows SystemD to feed a file containing a passphrase into
# the main Elasticsearch startup script

if [ -n "$ES_KEYSTORE_PASSPHRASE_FILE" ] ; then
exec /usr/share/elasticsearch/bin/elasticsearch "$@" < "$ES_KEYSTORE_PASSPHRASE_FILE"
else
exec /usr/share/elasticsearch/bin/elasticsearch "$@"
fi
17 changes: 15 additions & 2 deletions distribution/src/bin/elasticsearch
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ if [ -z "$ES_TMPDIR" ]; then
ES_TMPDIR=`"$JAVA" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.TempDirectory`
fi

# get keystore password before setting java options to avoid
# conflicting GC configurations for the keystore tools
unset KEYSTORE_PASSWORD
KEYSTORE_PASSWORD=
if ! echo $* | grep -E -q '(^-h |-h$| -h |--help$|--help |^-V |-V$| -V |--version$|--version )' \
&& "`dirname "$0"`"/elasticsearch-keystore has-passwd --silent
then
if ! read -s -r -p "Elasticsearch keystore password: " KEYSTORE_PASSWORD ; then
echo "Failed to read keystore password on console" 1>&2
exit 1
fi
fi

ES_JVM_OPTIONS="$ES_PATH_CONF"/jvm.options
ES_JAVA_OPTS=`export ES_TMPDIR; "$JAVA" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.JvmOptionsParser "$ES_JVM_OPTIONS"`

Expand All @@ -35,7 +48,7 @@ if ! echo $* | grep -E '(^-d |-d$| -d |--daemonize$|--daemonize )' > /dev/null;
-Des.bundled_jdk="$ES_BUNDLED_JDK" \
-cp "$ES_CLASSPATH" \
org.elasticsearch.bootstrap.Elasticsearch \
"$@"
"$@" <<<"$KEYSTORE_PASSWORD"
else
exec \
"$JAVA" \
Expand All @@ -48,7 +61,7 @@ else
-cp "$ES_CLASSPATH" \
org.elasticsearch.bootstrap.Elasticsearch \
"$@" \
<&- &
<<<"$KEYSTORE_PASSWORD" &
retval=$?
pid=$!
[ $retval -eq 0 ] || exit $retval
Expand Down
2 changes: 1 addition & 1 deletion distribution/src/bin/elasticsearch-cli.bat
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ set ES_JAVA_OPTS=-Xms4m -Xmx64m -XX:+UseSerialGC %ES_JAVA_OPTS%
-cp "%ES_CLASSPATH%" ^
"%ES_MAIN_CLASS%" ^
%*

exit /b %ERRORLEVEL%
42 changes: 41 additions & 1 deletion distribution/src/bin/elasticsearch.bat
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ setlocal enabledelayedexpansion
setlocal enableextensions

SET params='%*'
SET checkpassword=Y

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

IF "!current!" == "-h" (
SET checkpassword=N
)
IF "!current!" == "--help" (
SET checkpassword=N
)

IF "!current!" == "-V" (
SET checkpassword=N
)
IF "!current!" == "--version" (
SET checkpassword=N
)

IF "!silent!" == "Y" (
SET nopauseonerror=Y
) ELSE (
Expand All @@ -41,6 +56,18 @@ IF ERRORLEVEL 1 (
EXIT /B %ERRORLEVEL%
)

SET KEYSTORE_PASSWORD=
IF "%checkpassword%"=="Y" (
CALL "%~dp0elasticsearch-keystore.bat" has-passwd --silent
IF !ERRORLEVEL! EQU 0 (
SET /P KEYSTORE_PASSWORD=Elasticsearch keystore password:
IF !ERRORLEVEL! NEQ 0 (
ECHO Failed to read keystore password on standard input
EXIT /B !ERRORLEVEL!
)
)
)

if not defined ES_TMPDIR (
for /f "tokens=* usebackq" %%a in (`CALL %JAVA% -cp "!ES_CLASSPATH!" "org.elasticsearch.tools.launchers.TempDirectory"`) do set ES_TMPDIR=%%a
)
Expand All @@ -54,7 +81,20 @@ if "%MAYBE_JVM_OPTIONS_PARSER_FAILED%" == "jvm_options_parser_failed" (
exit /b 1
)

%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!
rem windows batch pipe will choke on special characters in strings
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^^=^^^^!
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^&=^^^&!
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^|=^^^|!
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^<=^^^<!
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^>=^^^>!
SET KEYSTORE_PASSWORD=!KEYSTORE_PASSWORD:^\=^^^\!
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is so much hacky overhead to retrieving and piping a password with windows batch commands. Switching to Powershell would make the situation better. But I'm wondering if we'll hit a point where it makes sense to move this processing into Java even for the first effort.


ECHO.!KEYSTORE_PASSWORD!| %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!

endlocal
endlocal
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.common.settings;

import joptsimple.OptionSet;
import org.elasticsearch.cli.KeyStoreAwareCommand;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.cli.UserException;
import org.elasticsearch.env.Environment;

import java.nio.file.Path;

public class HasPasswordKeyStoreCommand extends KeyStoreAwareCommand {

static final int NO_PASSWORD_EXIT_CODE = 1;

HasPasswordKeyStoreCommand() {
super("Succeeds if the keystore exists and is password-protected, " +
"fails with exit code " + NO_PASSWORD_EXIT_CODE + " otherwise.");
}

@Override
protected void execute(Terminal terminal, OptionSet options, Environment env) throws Exception {
final Path configFile = env.configFile();
final KeyStoreWrapper keyStore = KeyStoreWrapper.load(configFile);

// We handle error printing here so we can respect the "--silent" flag
// We have to throw an exception to get a nonzero exit code
if (keyStore == null) {
terminal.errorPrintln(Terminal.Verbosity.NORMAL, "ERROR: Elasticsearch keystore not found");
throw new UserException(NO_PASSWORD_EXIT_CODE, null);
}
if (keyStore.hasPassword() == false) {
terminal.errorPrintln(Terminal.Verbosity.NORMAL, "ERROR: Keystore is not password-protected");
throw new UserException(NO_PASSWORD_EXIT_CODE, null);
}

terminal.println(Terminal.Verbosity.NORMAL, "Keystore is password-protected");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ private KeyStoreCli() {
subcommands.put("remove", new RemoveSettingKeyStoreCommand());
subcommands.put("upgrade", new UpgradeKeyStoreCommand());
subcommands.put("passwd", new ChangeKeyStorePasswordCommand());
subcommands.put("has-passwd", new HasPasswordKeyStoreCommand());
}

public static void main(String[] args) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,30 @@
import org.elasticsearch.test.ESTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.ExpectedException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.Matchers.equalTo;

public class BootstrapTests extends ESTestCase {
Environment env;
List<FileSystem> fileSystems = new ArrayList<>();

private static final int MAX_PASSPHRASE_LENGTH = 10;

@Rule
public ExpectedException expectedException = ExpectedException.none();

@After
public void closeMockFileSystems() throws IOException {
IOUtils.close(fileSystems);
Expand All @@ -66,4 +78,47 @@ public void testLoadSecureSettings() throws Exception {
assertTrue(Files.exists(configPath.resolve("elasticsearch.keystore")));
}
}

public void testReadCharsFromStdin() throws Exception {
assertPassphraseRead("hello", "hello");
assertPassphraseRead("hello\n", "hello");
assertPassphraseRead("hello\r\n", "hello");

assertPassphraseRead("hellohello", "hellohello");
assertPassphraseRead("hellohello\n", "hellohello");
assertPassphraseRead("hellohello\r\n", "hellohello");

assertPassphraseRead("hello\nhi\n", "hello");
assertPassphraseRead("hello\r\nhi\r\n", "hello");
williamrandolph marked this conversation as resolved.
Show resolved Hide resolved
}

public void testPassphraseTooLong() throws Exception {
expectedException.expect(RuntimeException.class);
williamrandolph marked this conversation as resolved.
Show resolved Hide resolved
expectedException.expectMessage("Password exceeded maximum length of 10");
// read from an input stream to a character array
byte[] source = "hellohello!\n".getBytes(StandardCharsets.UTF_8);
try (InputStream stream = new ByteArrayInputStream(source)) {
Bootstrap.readPassphrase(stream, MAX_PASSPHRASE_LENGTH);
}
}

public void testNoPassPhraseProvided() throws Exception {
expectedException.expect(RuntimeException.class);
expectedException.expectMessage("Keystore passphrase required but none provided.");
// read from an input stream to a character array
byte[] source = "\r\n".getBytes(StandardCharsets.UTF_8);
try (InputStream stream = new ByteArrayInputStream(source)) {
Bootstrap.readPassphrase(stream, MAX_PASSPHRASE_LENGTH);
}
}

private void assertPassphraseRead(String source, String expected) {
try (InputStream stream = new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8))) {
char[] result = Bootstrap.readPassphrase(stream, MAX_PASSPHRASE_LENGTH);
assertThat(result, equalTo(expected.toCharArray()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

}
Loading