forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Password Protected Keystore (Feature Branch) (cleaned up) (elastic#49268
) * Reload secure settings with password (elastic#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 (elastic#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: elastic#32691 Supersedes: elastic#37472 * Restore behavior for force parameter (elastic#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 (elastic#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 (elastic#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 (elastic#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 (elastic#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.
- Loading branch information
1 parent
b6bf64b
commit e883395
Showing
71 changed files
with
2,419 additions
and
536 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
distribution/packages/src/common/systemd/systemd-entrypoint
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
...ols/keystore-cli/src/main/java/org/elasticsearch/common/settings/BaseKeyStoreCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* 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 joptsimple.OptionSpec; | ||
import org.elasticsearch.cli.ExitCodes; | ||
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 abstract class BaseKeyStoreCommand extends KeyStoreAwareCommand { | ||
|
||
private KeyStoreWrapper keyStore; | ||
private SecureString keyStorePassword; | ||
private final boolean keyStoreMustExist; | ||
OptionSpec<Void> forceOption; | ||
|
||
public BaseKeyStoreCommand(String description, boolean keyStoreMustExist) { | ||
super(description); | ||
this.keyStoreMustExist = keyStoreMustExist; | ||
} | ||
|
||
@Override | ||
protected final void execute(Terminal terminal, OptionSet options, Environment env) throws Exception { | ||
try { | ||
final Path configFile = env.configFile(); | ||
keyStore = KeyStoreWrapper.load(configFile); | ||
if (keyStore == null) { | ||
if (keyStoreMustExist) { | ||
throw new UserException(ExitCodes.DATA_ERROR, "Elasticsearch keystore not found at [" + | ||
KeyStoreWrapper.keystorePath(env.configFile()) + "]. Use 'create' command to create one."); | ||
} else if (options.has(forceOption) == false) { | ||
if (terminal.promptYesNo("The elasticsearch keystore does not exist. Do you want to create it?", false) == false) { | ||
terminal.println("Exiting without creating keystore."); | ||
return; | ||
} | ||
} | ||
keyStorePassword = new SecureString(new char[0]); | ||
keyStore = KeyStoreWrapper.create(); | ||
keyStore.save(configFile, keyStorePassword.getChars()); | ||
} else { | ||
keyStorePassword = keyStore.hasPassword() ? readPassword(terminal, false) : new SecureString(new char[0]); | ||
keyStore.decrypt(keyStorePassword.getChars()); | ||
} | ||
executeCommand(terminal, options, env); | ||
} catch (SecurityException e) { | ||
throw new UserException(ExitCodes.DATA_ERROR, e.getMessage()); | ||
} finally { | ||
if (keyStorePassword != null) { | ||
keyStorePassword.close(); | ||
} | ||
} | ||
} | ||
|
||
protected KeyStoreWrapper getKeyStore() { | ||
return keyStore; | ||
} | ||
|
||
protected SecureString getKeyStorePassword() { | ||
return keyStorePassword; | ||
} | ||
|
||
/** | ||
* This is called after the keystore password has been read from the stdin and the keystore is decrypted and | ||
* loaded. The keystore and keystore passwords are available to classes extending {@link BaseKeyStoreCommand} | ||
* using {@link BaseKeyStoreCommand#getKeyStore()} and {@link BaseKeyStoreCommand#getKeyStorePassword()} | ||
* respectively. | ||
*/ | ||
protected abstract void executeCommand(Terminal terminal, OptionSet options, Environment env) throws Exception; | ||
} |
47 changes: 47 additions & 0 deletions
47
...re-cli/src/main/java/org/elasticsearch/common/settings/ChangeKeyStorePasswordCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* 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.ExitCodes; | ||
import org.elasticsearch.cli.Terminal; | ||
import org.elasticsearch.cli.UserException; | ||
import org.elasticsearch.env.Environment; | ||
|
||
/** | ||
* A sub-command for the keystore cli which changes the password. | ||
*/ | ||
class ChangeKeyStorePasswordCommand extends BaseKeyStoreCommand { | ||
|
||
ChangeKeyStorePasswordCommand() { | ||
super("Changes the password of a keystore", true); | ||
} | ||
|
||
@Override | ||
protected void executeCommand(Terminal terminal, OptionSet options, Environment env) throws Exception { | ||
try (SecureString newPassword = readPassword(terminal, true)) { | ||
final KeyStoreWrapper keyStore = getKeyStore(); | ||
keyStore.save(env.configFile(), newPassword.getChars()); | ||
terminal.println("Elasticsearch keystore password changed successfully."); | ||
} catch (SecurityException e) { | ||
throw new UserException(ExitCodes.DATA_ERROR, e.getMessage()); | ||
} | ||
} | ||
} |
Oops, something went wrong.