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

Reset elastic password cli tool #74892

Merged
merged 22 commits into from
Jul 20, 2021
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
104617d
Add a tool for creating enrollment tokens
jkakavas Jul 1, 2021
f67eaf1
elastic user password reset CLI tool
jkakavas Jul 3, 2021
173ce85
Merge remote-tracking branch 'origin/master' into reset-elastic-passw…
jkakavas Jul 4, 2021
3776bb9
qa test
jkakavas Jul 4, 2021
d6d9385
add docs
jkakavas Jul 5, 2021
7497bc9
support batch silent mode
jkakavas Jul 5, 2021
ad30c3b
remove leftover files
jkakavas Jul 5, 2021
c5c1759
Bring along updates from #74890
jkakavas Jul 8, 2021
7efae2c
Merge remote-tracking branch 'origin/master' into reset-elastic-passw…
jkakavas Jul 8, 2021
a40f4cc
Merge feedback from 74890
jkakavas Jul 12, 2021
f75e2db
Merge remote-tracking branch 'origin/master' into reset-elastic-passw…
jkakavas Jul 12, 2021
4d8cfa4
Include error code in exception message
jkakavas Jul 12, 2021
1f14b39
don't explicitly check for multiple file realms, node does that already
jkakavas Jul 12, 2021
ed292c4
Add link in top-level page
Jul 13, 2021
704b4d8
Apply doc suggestions from code review
jkakavas Jul 13, 2021
cc2404c
More suggestions from doc review
jkakavas Jul 13, 2021
cb87765
Merge remote-tracking branch 'origin/master' into reset-elastic-passw…
jkakavas Jul 14, 2021
aa73e85
Add note that you can't use the CLI if the file realm is disabled
Jul 14, 2021
0d7c7aa
Merge remote-tracking branch 'origin/master' into reset-elastic-passw…
jkakavas Jul 15, 2021
c2c64cf
Merge remote-tracking branch 'origin/master' into reset-elastic-passw…
jkakavas Jul 20, 2021
4a246cd
message
jkakavas Jul 20, 2021
d8eaca9
Fix package in CLI tool
jkakavas Jul 20, 2021
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
2 changes: 2 additions & 0 deletions docs/reference/commands/index.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ tasks from the command line:
* <<elasticsearch-croneval>>
* <<elasticsearch-keystore>>
* <<node-tool>>
* <<reset-elastic-password>>
* <<saml-metadata>>
* <<setup-passwords>>
* <<shard-tool>>
Expand All @@ -25,6 +26,7 @@ include::certutil.asciidoc[]
include::croneval.asciidoc[]
include::keystore.asciidoc[]
include::node-tool.asciidoc[]
include::reset-elastic-password.asciidoc[]
include::saml-metadata.asciidoc[]
include::service-tokens-command.asciidoc[]
include::setup-passwords.asciidoc[]
Expand Down
57 changes: 57 additions & 0 deletions docs/reference/commands/reset-elastic-password.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[roles="xpack"]
[[reset-elastic-password]]
== elasticsearch-reset-elastic-password

The `elasticsearch-reset-elastic-password` command resets the password for the
`elastic` <<built-in-users,built-in superuser>>.

[discrete]
=== Synopsis

[source,shell]
----
bin/elasticsearch-reset-elastic-password
[-a, --auto] [-b, --batch] [-h, --help]
[-E <KeyValuePair] [-i, --interactive]
----

[discrete]
=== Description

This command resets the password of the `elastic` superuser. By default, a
strong password is generated for you. If you wish to choose the password, you
can run the tool in interactive mode with `-i`, where you will be prompted to
enter the desired password. It uses a temporary superuser in the
<<file-realm, file realm>> that is automatically generated and then removed,
in order to submit the request to change the `elastic` user password.
jkakavas marked this conversation as resolved.
Show resolved Hide resolved

This command uses an HTTP connection to connect to the cluster and run the user
management requests. The command automatically attempts to establish the connection
over HTTPS by using the `xpack.security.http.ssl` settings in
the `elasticsearch.yml` file. If you do not use the default config directory
location, ensure that the *ES_PATH_CONF* environment variable returns the
correct path before you run the `elasticsearch-create-enrollment-token` command. You can
jkakavas marked this conversation as resolved.
Show resolved Hide resolved
override settings in your `elasticsearch.yml` file by using the `-E` command
option. For more information about debugging connection failures, see
<<trb-security-setup>>.

[discrete]
[[reset-elastic-password-parameters]]
=== Parameters

`-a, --auto`:: Reset the password of `elastic` to an auto-generated strong password. (Default)
jkakavas marked this conversation as resolved.
Show resolved Hide resolved

`-b, --batch`:: If enabled, runs the reset password process without prompting the user for verification.
jkakavas marked this conversation as resolved.
Show resolved Hide resolved

jkakavas marked this conversation as resolved.
Show resolved Hide resolved
jkakavas marked this conversation as resolved.
Show resolved Hide resolved
`-i, --interactive`:: When specified, the tool prompts the user for the password of the `elastic` user.
jkakavas marked this conversation as resolved.
Show resolved Hide resolved
jkakavas marked this conversation as resolved.
Show resolved Hide resolved

[discrete]
=== Examples

The following example resets the password of the `elastic` user to an auto-generated value and
prints the new password in the console.

[source,shell]
----
bin/elasticsearch-reset-elastic-password
----
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.

ES_MAIN_CLASS=org.elasticsearch.xpack.security.enrollment.tool.CreateEnrollmentTokenTool \
ES_ADDITIONAL_SOURCES="x-pack-env;x-pack-security-env" \
"`dirname "$0"`"/elasticsearch-cli \
"$@"
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.

ES_MAIN_CLASS=org.elasticsearch.xpack.security.tool.ResetElasticPasswordTool \
ES_ADDITIONAL_SOURCES="x-pack-env;x-pack-security-env" \
"`dirname "$0"`"/elasticsearch-cli \
"$@"
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@echo off

rem Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
rem or more contributor license agreements. Licensed under the Elastic License
rem 2.0; you may not use this file except in compliance with the Elastic License
rem 2.0.

setlocal enabledelayedexpansion
setlocal enableextensions

set ES_MAIN_CLASS=org.elasticsearch.xpack.security.tool.ResetElasticPasswordTool
set ES_ADDITIONAL_SOURCES=x-pack-env;x-pack-security-env
set ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli
call "%~dp0elasticsearch-cli.bat" ^
%%* ^
|| goto exit

endlocal
endlocal
:exit
exit /b %ERRORLEVEL%
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.security.enrollment.tool;

import joptsimple.OptionSet;
import joptsimple.OptionSpec;

import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.cli.UserException;
import org.elasticsearch.common.settings.KeyStoreWrapper;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.core.CheckedFunction;
import org.elasticsearch.env.Environment;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.security.enrollment.CreateEnrollmentToken;
import org.elasticsearch.xpack.security.tool.BaseRunAsSuperuserCommand;
import org.elasticsearch.xpack.security.tool.CommandLineHttpClient;

import java.util.List;
import java.util.function.Function;

public class CreateEnrollmentTokenTool extends BaseRunAsSuperuserCommand {

private final OptionSpec<String> scope;
private final CheckedFunction<Environment, CreateEnrollmentToken, Exception> createEnrollmentTokenFunction;
static final List<String> ALLOWED_SCOPES = List.of("node", "kibana");

CreateEnrollmentTokenTool() {
this(
environment -> new CommandLineHttpClient(environment),
environment -> KeyStoreWrapper.load(environment.configFile()),
environment -> new CreateEnrollmentToken(environment)
);
}

CreateEnrollmentTokenTool(
Function<Environment, CommandLineHttpClient> clientFunction,
CheckedFunction<Environment, KeyStoreWrapper, Exception> keyStoreFunction,
CheckedFunction<Environment, CreateEnrollmentToken, Exception> createEnrollmentTokenFunction
) {
super(clientFunction, keyStoreFunction, "Creates enrollment tokens for elasticsearch nodes and kibana instances");
Copy link
Contributor

Choose a reason for hiding this comment

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

As I understand this supposed to be a help message (Command$printHelp)

Copy link
Member Author

Choose a reason for hiding this comment

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

The description of the command is printed when the command is run with -h , yes. Can you elaborate on what your comment was about ? Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

I would expect a description of allowed parameters (like node/kibana)

Copy link
Member Author

Choose a reason for hiding this comment

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

I would expect a description of allowed parameters (like node/kibana)

We don't put these in the description of the command. All of our CLI tools extend Command and it calls printHelp when the -h parameter is passed ( or on error ). printHelp prints the parameters and their description.

FWIW, the ouput of the -h is

Creates enrollment tokens for elasticsearch nodes and kibana instances

Option (* = required)  Description                                             
---------------------  -----------                                             
-E <KeyValuePair>      Configure a setting                                     
-f, --force            Use this option to force execution of the command       
                         against a cluster that is currently unhealthy.        
-h, --help             Show help                                               
* -s, --scope          The scope of this enrollment token, can be either "node"
                         or "kibana"                                           
-v, --verbose          Show verbose output        

jkakavas marked this conversation as resolved.
Show resolved Hide resolved
this.createEnrollmentTokenFunction = createEnrollmentTokenFunction;
scope = parser.acceptsAll(List.of("scope", "s"), "The scope of this enrollment token, can be either \"node\" or \"kibana\"")
.withRequiredArg()
.required();
}

public static void main(String[] args) throws Exception {
exit(new CreateEnrollmentTokenTool().main(args, Terminal.DEFAULT));
}

@Override
protected void validate(Terminal terminal, OptionSet options, Environment env) throws Exception {
if (XPackSettings.ENROLLMENT_ENABLED.get(env.settings()) == false) {
throw new UserException(
ExitCodes.CONFIG,
"[xpack.security.enrollment.enabled] must be set to `true` to create an enrollment token"
);
}
final String tokenScope = scope.value(options);
if (ALLOWED_SCOPES.contains(tokenScope) == false) {
terminal.errorPrintln("The scope of this enrollment token, can only be one of " + ALLOWED_SCOPES);
BigPandaToo marked this conversation as resolved.
Show resolved Hide resolved
throw new UserException(ExitCodes.USAGE, "Invalid scope");
}
}

@Override
protected void executeCommand(Terminal terminal, OptionSet options, Environment env) throws Exception {
final String username = getUsername();
final String tokenScope = scope.value(options);
try (SecureString password = getPassword()) {
CreateEnrollmentToken createEnrollmentTokenService = createEnrollmentTokenFunction.apply(env);
if (tokenScope.equals("node")) {
terminal.println(createEnrollmentTokenService.createNodeEnrollmentToken(username, password));
} else {
terminal.println(createEnrollmentTokenService.createKibanaEnrollmentToken(username, password));
}
} catch (Exception e) {
terminal.errorPrintln("Unable to create enrollment token for scope [" + tokenScope + "]");
throw new UserException(ExitCodes.CANT_CREATE, e.getMessage(), e.getCause());
}
}
}
Loading