diff --git a/docs/reference/commands/create-enrollment-token.asciidoc b/docs/reference/commands/create-enrollment-token.asciidoc index 4fd95f1b7bef4..ca95649324702 100644 --- a/docs/reference/commands/create-enrollment-token.asciidoc +++ b/docs/reference/commands/create-enrollment-token.asciidoc @@ -12,7 +12,7 @@ The `elasticsearch-create-enrollment-token` command creates enrollment tokens fo [source,shell] ---- bin/elasticsearch-create-enrollment-token -[-f, --force] [-h, --help] [-E ] [-s, --scope] +[-f, --force] [-h, --help] [-E ] [-s, --scope] [--url] ---- [discrete] @@ -23,7 +23,7 @@ Use this command to create enrollment tokens, which you can use to enroll new with an existing {es} cluster that has security features enabled. The command generates (and subsequently removes) a temporary user in the <> to run the request that creates enrollment tokens. -IMPORTANT: You cannot use this tool if the file realm is disabled in your +IMPORTANT: You cannot use this tool if the file realm is disabled in your `elasticsearch.yml` file. This command uses an HTTP connection to connect to the cluster and run the user @@ -42,12 +42,17 @@ option. For more information about debugging connection failures, see `-E `:: Configures a standard {es} or {xpack} setting. -`-f, --force`:: Forces the command to run against an unhealthy cluster. +`-f, --force`:: Forces the command to run against an unhealthy cluster. `-h, --help`:: Returns all of the command parameters. `-s, --scope`:: Specifies the scope of the generated token. Supported values are `node` and `kibana`. +`--url`:: Specifies the base URL (hostname and port of the local node) that the tool uses to submit API +requests to {es}. The default value is determined from the settings in your +`elasticsearch.yml` file. If `xpack.security.http.ssl.enabled` is set to `true`, +you must specify an HTTPS URL. + [discrete] === Examples @@ -57,3 +62,12 @@ The following command creates an enrollment token for enrolling an {es} node int ---- bin/elasticsearch-create-enrollment-token -s node ---- + +The following command creates an enrollment token for enrolling a {kib} instance into a cluster. +The specified URL indicates where the elasticsearch-create-enrollment-token tool attempts to reach the +local {es} node: + +[source,shell] +---- +bin/elasticsearch-create-enrollment-token -s kibana --url "https://172.0.0.3:9200" +---- diff --git a/docs/reference/commands/reset-password.asciidoc b/docs/reference/commands/reset-password.asciidoc index 012874fd61171..b8823158d0d0f 100644 --- a/docs/reference/commands/reset-password.asciidoc +++ b/docs/reference/commands/reset-password.asciidoc @@ -14,7 +14,7 @@ the native realm and built-in users. bin/elasticsearch-reset-password [-a, --auto] [-b, --batch] [-E , String> httpInfo = getNodeInfo(user, password); + final String apiKey = getApiKeyCredentials(user, password, action, baseUrl); + final Tuple, String> httpInfo = getNodeInfo(user, password, baseUrl); return new EnrollmentToken(apiKey, fingerprint, httpInfo.v2(), httpInfo.v1()); } @@ -89,12 +87,12 @@ private HttpResponse.HttpResponseBuilder responseBuilder(InputStream is) throws return httpResponseBuilder; } - protected URL createAPIKeyUrl() throws MalformedURLException, URISyntaxException { - return new URL(defaultUrl, (defaultUrl.toURI().getPath() + "/_security/api_key").replaceAll("/+", "/")); + protected URL createAPIKeyUrl(URL baseUrl) throws MalformedURLException, URISyntaxException { + return new URL(baseUrl, (baseUrl.toURI().getPath() + "/_security/api_key").replaceAll("/+", "/")); } - protected URL getHttpInfoUrl() throws MalformedURLException, URISyntaxException { - return new URL(defaultUrl, (defaultUrl.toURI().getPath() + "/_nodes/_local/http").replaceAll("/+", "/")); + protected URL getHttpInfoUrl(URL baseUrl) throws MalformedURLException, URISyntaxException { + return new URL(baseUrl, (baseUrl.toURI().getPath() + "/_nodes/_local/http").replaceAll("/+", "/")); } @SuppressWarnings("unchecked") @@ -114,7 +112,7 @@ static String getVersion(Map nodesInfo) { return nodeInfo.get("version").toString(); } - protected String getApiKeyCredentials(String user, SecureString password, String action) throws Exception { + protected String getApiKeyCredentials(String user, SecureString password, String action, URL baseUrl) throws Exception { final CheckedSupplier createApiKeyRequestBodySupplier = () -> { XContentBuilder xContentBuilder = JsonXContent.contentBuilder(); xContentBuilder.startObject() @@ -129,7 +127,7 @@ protected String getApiKeyCredentials(String user, SecureString password, String return Strings.toString(xContentBuilder); }; - final URL createApiKeyUrl = createAPIKeyUrl(); + final URL createApiKeyUrl = createAPIKeyUrl(baseUrl); final HttpResponse httpResponseApiKey = client.execute( "POST", createApiKeyUrl, @@ -155,8 +153,8 @@ protected String getApiKeyCredentials(String user, SecureString password, String return apiId + ":" + apiKey; } - protected Tuple, String> getNodeInfo(String user, SecureString password) throws Exception { - final URL httpInfoUrl = getHttpInfoUrl(); + protected Tuple, String> getNodeInfo(String user, SecureString password, URL baseUrl) throws Exception { + final URL httpInfoUrl = getHttpInfoUrl(baseUrl); final HttpResponse httpResponseHttp = client.execute("GET", httpInfoUrl, user, password, () -> null, is -> responseBuilder(is)); final int httpCode = httpResponseHttp.getHttpStatus(); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/enrollment/tool/CreateEnrollmentTokenTool.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/enrollment/tool/CreateEnrollmentTokenTool.java index 84c6ccf4964ea..954badc86e47a 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/enrollment/tool/CreateEnrollmentTokenTool.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/enrollment/tool/CreateEnrollmentTokenTool.java @@ -22,16 +22,19 @@ import org.elasticsearch.xpack.security.enrollment.ExternalEnrollmentTokenGenerator; import org.elasticsearch.xpack.security.tool.BaseRunAsSuperuserCommand; +import java.net.URL; import java.util.List; import java.util.function.Function; public class CreateEnrollmentTokenTool extends BaseRunAsSuperuserCommand { private final OptionSpec scope; + private final Function clientFunction; private final CheckedFunction createEnrollmentTokenFunction; static final List ALLOWED_SCOPES = List.of("node", "kibana"); CreateEnrollmentTokenTool() { + this( environment -> new CommandLineHttpClient(environment), environment -> KeyStoreWrapper.load(environment.configFile()), @@ -46,6 +49,7 @@ public class CreateEnrollmentTokenTool extends BaseRunAsSuperuserCommand { ) { super(clientFunction, keyStoreFunction, "Creates enrollment tokens for elasticsearch nodes and kibana instances"); this.createEnrollmentTokenFunction = createEnrollmentTokenFunction; + this.clientFunction = clientFunction; scope = parser.acceptsAll(List.of("scope", "s"), "The scope of this enrollment token, can be either \"node\" or \"kibana\"") .withRequiredArg() .required(); @@ -74,12 +78,15 @@ protected void validate(Terminal terminal, OptionSet options, Environment env) t protected void executeCommand(Terminal terminal, OptionSet options, Environment env, String username, SecureString password) throws Exception { final String tokenScope = scope.value(options); + final URL baseUrl = options.has(urlOption) + ? new URL(options.valueOf(urlOption)) + : new URL(clientFunction.apply(env).getDefaultURL()); try { ExternalEnrollmentTokenGenerator externalEnrollmentTokenGenerator = createEnrollmentTokenFunction.apply(env); if (tokenScope.equals("node")) { - terminal.println(externalEnrollmentTokenGenerator.createNodeEnrollmentToken(username, password).getEncoded()); + terminal.println(externalEnrollmentTokenGenerator.createNodeEnrollmentToken(username, password, baseUrl).getEncoded()); } else { - terminal.println(externalEnrollmentTokenGenerator.createKibanaEnrollmentToken(username, password).getEncoded()); + terminal.println(externalEnrollmentTokenGenerator.createKibanaEnrollmentToken(username, password, baseUrl).getEncoded()); } } catch (Exception e) { terminal.errorPrintln("Unable to create enrollment token for scope [" + tokenScope + "]"); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/tool/BaseRunAsSuperuserCommand.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/tool/BaseRunAsSuperuserCommand.java index 6909da4df03bb..c0ed18d0dc6b9 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/tool/BaseRunAsSuperuserCommand.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/tool/BaseRunAsSuperuserCommand.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.security.tool; import joptsimple.OptionSet; +import joptsimple.OptionSpec; import joptsimple.OptionSpecBuilder; import org.elasticsearch.Version; @@ -57,6 +58,7 @@ public abstract class BaseRunAsSuperuserCommand extends KeyStoreAwareCommand { private static final int PASSWORD_LENGTH = 14; private final OptionSpecBuilder force; + protected final OptionSpec urlOption; private final Function clientFunction; private final CheckedFunction keyStoreFunction; @@ -72,6 +74,7 @@ public BaseRunAsSuperuserCommand( List.of("f", "force"), "Use this option to force execution of the command against a cluster that is currently unhealthy." ); + urlOption = parser.accepts("url", "the URL where the elasticsearch node listens for connections.").withRequiredArg(); } @Override @@ -120,7 +123,7 @@ protected final void execute(Terminal terminal, OptionSet options, Environment e attributesChecker.check(terminal); final boolean forceExecution = options.has(force); - checkClusterHealthWithRetries(newEnv, terminal, username, password, 5, forceExecution); + checkClusterHealthWithRetries(newEnv, options, terminal, username, password, 5, forceExecution); executeCommand(terminal, options, newEnv, username, password); } catch (Exception e) { int exitCode; @@ -195,6 +198,7 @@ private void ensureFileRealmEnabled(Settings settings) throws Exception { */ private void checkClusterHealthWithRetries( Environment env, + OptionSet options, Terminal terminal, String username, SecureString password, @@ -202,7 +206,8 @@ private void checkClusterHealthWithRetries( boolean force ) throws Exception { CommandLineHttpClient client = clientFunction.apply(env); - final URL clusterHealthUrl = CommandLineHttpClient.createURL(new URL(client.getDefaultURL()), "_cluster/health", "?pretty"); + final URL baseUrl = options.has(urlOption) ? new URL(options.valueOf(urlOption)) : new URL(client.getDefaultURL()); + final URL clusterHealthUrl = CommandLineHttpClient.createURL(baseUrl, "_cluster/health", "?pretty"); final HttpResponse response; try { response = client.execute("GET", clusterHealthUrl, username, password, () -> null, CommandLineHttpClient::responseBuilder); @@ -225,7 +230,7 @@ private void checkClusterHealthWithRetries( ); Thread.sleep(1000); retries -= 1; - checkClusterHealthWithRetries(env, terminal, username, password, retries, force); + checkClusterHealthWithRetries(env, options, terminal, username, password, retries, force); } else { throw new UserException( ExitCodes.DATA_ERROR, diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/enrollment/ExternalEnrollmentTokenGeneratorTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/enrollment/ExternalEnrollmentTokenGeneratorTests.java index 63824c270e7c9..339b3de9ecb49 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/enrollment/ExternalEnrollmentTokenGeneratorTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/enrollment/ExternalEnrollmentTokenGeneratorTests.java @@ -83,10 +83,10 @@ public void setupMocks() throws Exception { public void testCreateSuccess() throws Exception { final CommandLineHttpClient client = mock(CommandLineHttpClient.class); - when(client.getDefaultURL()).thenReturn("http://localhost:9200"); final ExternalEnrollmentTokenGenerator externalEnrollmentTokenGenerator = new ExternalEnrollmentTokenGenerator(environment, client); - final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(); - final URL getHttpInfoURL = externalEnrollmentTokenGenerator.getHttpInfoUrl(); + final URL baseURL = new URL("http://localhost:9200"); + final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(baseURL); + final URL getHttpInfoURL = externalEnrollmentTokenGenerator.getHttpInfoUrl(baseURL); final HttpResponse httpResponseOK = new HttpResponse(HttpURLConnection.HTTP_OK, new HashMap<>()); when(client.execute(anyString(), any(URL.class), anyString(), any(SecureString.class), anyCheckedSupplier(), anyCheckedFunction())) @@ -147,7 +147,8 @@ public void testCreateSuccess() throws Exception { final String tokenNode = externalEnrollmentTokenGenerator.createNodeEnrollmentToken( "elastic", - new SecureString("elastic".toCharArray()) + new SecureString("elastic".toCharArray()), + baseURL ).getEncoded(); Map infoNode = getDecoded(tokenNode); @@ -158,7 +159,8 @@ public void testCreateSuccess() throws Exception { final String tokenKibana = externalEnrollmentTokenGenerator.createKibanaEnrollmentToken( "elastic", - new SecureString("elastic".toCharArray()) + new SecureString("elastic".toCharArray()), + baseURL ).getEncoded(); Map infoKibana = getDecoded(tokenKibana); @@ -170,9 +172,9 @@ public void testCreateSuccess() throws Exception { public void testFailedCreateApiKey() throws Exception { final CommandLineHttpClient client = mock(CommandLineHttpClient.class); - when(client.getDefaultURL()).thenReturn("http://localhost:9200"); + final URL baseURL = new URL("http://localhost:9200"); final ExternalEnrollmentTokenGenerator externalEnrollmentTokenGenerator = new ExternalEnrollmentTokenGenerator(environment, client); - final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(); + final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(baseURL); final HttpResponse httpResponseNotOK = new HttpResponse(HttpURLConnection.HTTP_BAD_REQUEST, new HashMap<>()); when( @@ -188,7 +190,7 @@ public void testFailedCreateApiKey() throws Exception { IllegalStateException ex = expectThrows( IllegalStateException.class, - () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray())) + () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray()), baseURL) .getEncoded() ); assertThat(ex.getMessage(), Matchers.containsString("Unexpected response code [400] from calling POST ")); @@ -196,10 +198,10 @@ public void testFailedCreateApiKey() throws Exception { public void testFailedRetrieveHttpInfo() throws Exception { final CommandLineHttpClient client = mock(CommandLineHttpClient.class); - when(client.getDefaultURL()).thenReturn("http://localhost:9200"); + final URL baseURL = new URL("http://localhost:9200"); final ExternalEnrollmentTokenGenerator externalEnrollmentTokenGenerator = new ExternalEnrollmentTokenGenerator(environment, client); - final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(); - final URL getHttpInfoURL = externalEnrollmentTokenGenerator.getHttpInfoUrl(); + final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(baseURL); + final URL getHttpInfoURL = externalEnrollmentTokenGenerator.getHttpInfoUrl(baseURL); final HttpResponse httpResponseOK = new HttpResponse(HttpURLConnection.HTTP_OK, new HashMap<>()); when( @@ -248,7 +250,7 @@ public void testFailedRetrieveHttpInfo() throws Exception { IllegalStateException ex = expectThrows( IllegalStateException.class, - () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray())) + () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray()), baseURL) .getEncoded() ); assertThat(ex.getMessage(), Matchers.containsString("Unexpected response code [400] from calling GET ")); @@ -274,10 +276,10 @@ public void testFailedNoCaInKeystore() throws Exception { .build(); environment = new Environment(settings, tempDir); final CommandLineHttpClient client = mock(CommandLineHttpClient.class); - when(client.getDefaultURL()).thenReturn("http://localhost:9200"); final ExternalEnrollmentTokenGenerator externalEnrollmentTokenGenerator = new ExternalEnrollmentTokenGenerator(environment, client); - final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(); - final URL getHttpInfoURL = externalEnrollmentTokenGenerator.getHttpInfoUrl(); + final URL baseURL = new URL("http://localhost:9200"); + final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(baseURL); + final URL getHttpInfoURL = externalEnrollmentTokenGenerator.getHttpInfoUrl(baseURL); final HttpResponse httpResponseOK = new HttpResponse(HttpURLConnection.HTTP_OK, new HashMap<>()); when( @@ -326,7 +328,7 @@ public void testFailedNoCaInKeystore() throws Exception { IllegalStateException ex = expectThrows( IllegalStateException.class, - () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray())) + () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray()), baseURL) .getEncoded() ); assertThat( @@ -358,10 +360,10 @@ public void testFailedManyCaInKeystore() throws Exception { .build(); environment = new Environment(settings, tempDir); final CommandLineHttpClient client = mock(CommandLineHttpClient.class); - when(client.getDefaultURL()).thenReturn("http://localhost:9200"); final ExternalEnrollmentTokenGenerator externalEnrollmentTokenGenerator = new ExternalEnrollmentTokenGenerator(environment, client); - final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(); - final URL getHttpInfoURL = externalEnrollmentTokenGenerator.getHttpInfoUrl(); + final URL baseURL = new URL("http://localhost:9200"); + final URL createAPIKeyURL = externalEnrollmentTokenGenerator.createAPIKeyUrl(baseURL); + final URL getHttpInfoURL = externalEnrollmentTokenGenerator.getHttpInfoUrl(baseURL); final HttpResponse httpResponseOK = new HttpResponse(HttpURLConnection.HTTP_OK, new HashMap<>()); when( @@ -410,7 +412,7 @@ public void testFailedManyCaInKeystore() throws Exception { IllegalStateException ex = expectThrows( IllegalStateException.class, - () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray())) + () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray()), baseURL) .getEncoded() ); assertThat( @@ -431,7 +433,7 @@ public void testNoKeyStore() throws Exception { .build(); final Environment environment_no_keystore = new Environment(settings, tempDir); final CommandLineHttpClient client = mock(CommandLineHttpClient.class); - when(client.getDefaultURL()).thenReturn("http://localhost:9200"); + final URL baseURL = new URL("http://localhost:9200"); final ExternalEnrollmentTokenGenerator externalEnrollmentTokenGenerator = new ExternalEnrollmentTokenGenerator( environment_no_keystore, client @@ -439,7 +441,7 @@ public void testNoKeyStore() throws Exception { IllegalStateException ex = expectThrows( IllegalStateException.class, - () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray())) + () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray()), baseURL) .getEncoded() ); assertThat( @@ -467,7 +469,7 @@ public void testEnrollmentNotEnabled() throws Exception { .build(); final Environment environment_not_enabled = new Environment(settings, tempDir); final CommandLineHttpClient client = mock(CommandLineHttpClient.class); - when(client.getDefaultURL()).thenReturn("http://localhost:9200"); + final URL baseURL = new URL("http://localhost:9200"); final ExternalEnrollmentTokenGenerator externalEnrollmentTokenGenerator = new ExternalEnrollmentTokenGenerator( environment_not_enabled, client @@ -475,7 +477,7 @@ public void testEnrollmentNotEnabled() throws Exception { IllegalStateException ex = expectThrows( IllegalStateException.class, - () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray())) + () -> externalEnrollmentTokenGenerator.createNodeEnrollmentToken("elastic", new SecureString("elastic".toCharArray()), baseURL) .getEncoded() ); assertThat( diff --git a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/ResetPasswordToolTests.java b/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/ResetPasswordToolTests.java index 330df329b4ded..943b2770172a5 100644 --- a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/ResetPasswordToolTests.java +++ b/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/ResetPasswordToolTests.java @@ -152,6 +152,39 @@ public void testSuccessInteractiveMode() throws Exception { assertThat(output, containsString("Password for the [" + user + "] user successfully reset.")); } + public void testUserCanPassUrlParameter() throws Exception { + URL url = new URL("http://localhost:9204"); + HttpResponse healthResponse = new HttpResponse(HttpURLConnection.HTTP_OK, Map.of("status", randomFrom("yellow", "green"))); + when( + client.execute( + anyString(), + eq(clusterHealthUrl(url)), + anyString(), + any(SecureString.class), + any(CheckedSupplier.class), + any(CheckedFunction.class) + ) + ).thenReturn(healthResponse); + HttpResponse changePasswordResponse = new HttpResponse(HttpURLConnection.HTTP_OK, Map.of()); + when( + client.execute( + anyString(), + eq(changePasswordUrl(url, user)), + anyString(), + any(SecureString.class), + any(CheckedSupplier.class), + any(CheckedFunction.class) + ) + ).thenReturn(changePasswordResponse); + terminal.addTextInput("y"); + execute(randomFrom("-u", "--username"), user, "--url", "http://localhost:9204"); + String output = terminal.getOutput(); + assertThat(output, containsString("This tool will reset the password of the [" + user + "] user to an autogenerated value.")); + assertThat(output, containsString("The password will be printed in the console.")); + assertThat(output, containsString("Password for the [" + user + "] user successfully reset.")); + assertThat(output, containsString("New value:")); + } + public void testUserCancelledAutoMode() throws Exception { terminal.addTextInput("n"); UserException e = expectThrows(UserException.class, () -> execute(randomFrom("-u", "--username"), user)); diff --git a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/security/enrollment/tool/CreateEnrollmentTokenToolTests.java b/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/security/enrollment/tool/CreateEnrollmentTokenToolTests.java index 16c7120ab3a76..d322ae2cfdc5d 100644 --- a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/security/enrollment/tool/CreateEnrollmentTokenToolTests.java +++ b/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/security/enrollment/tool/CreateEnrollmentTokenToolTests.java @@ -134,8 +134,12 @@ public void setup() throws Exception { "8.0.0", Arrays.asList("[192.168.0.1:9201, 172.16.254.1:9202") ); - when(externalEnrollmentTokenGenerator.createKibanaEnrollmentToken(anyString(), any(SecureString.class))).thenReturn(kibanaToken); - when(externalEnrollmentTokenGenerator.createNodeEnrollmentToken(anyString(), any(SecureString.class))).thenReturn(nodeToken); + when(externalEnrollmentTokenGenerator.createKibanaEnrollmentToken(anyString(), any(SecureString.class), any(URL.class))).thenReturn( + kibanaToken + ); + when(externalEnrollmentTokenGenerator.createNodeEnrollmentToken(anyString(), any(SecureString.class), any(URL.class))).thenReturn( + nodeToken + ); } @AfterClass @@ -167,6 +171,36 @@ public void testInvalidScope() throws Exception { ); } + public void testUserCanPassUrl() throws Exception { + HttpResponse healthResponse = new HttpResponse(HttpURLConnection.HTTP_OK, Map.of("status", randomFrom("yellow", "green"))); + when( + client.execute( + anyString(), + eq(clusterHealthUrl(new URL("http://localhost:9204"))), + anyString(), + any(SecureString.class), + any(CheckedSupplier.class), + any(CheckedFunction.class) + ) + ).thenReturn(healthResponse); + EnrollmentToken kibanaToken = new EnrollmentToken( + "DR6CzXkBDf8amV_48yYX:x3YqU_rqQwm-ESrkExcnOg", + "ce480d53728605674fcfd8ffb51000d8a33bf32de7c7f1e26b4d428f8a91362d", + "8.0.0", + Arrays.asList("[192.168.0.1:9201, 172.16.254.1:9202") + ); + when( + externalEnrollmentTokenGenerator.createKibanaEnrollmentToken( + anyString(), + any(SecureString.class), + eq(new URL("http://localhost:9204")) + ) + ).thenReturn(kibanaToken); + String output = execute("--scope", "kibana", "--url", "http://localhost:9204"); + assertThat(output, containsString("1WXzQ4eVlYOngzWXFVX3JxUXdtLUVTcmtFeGNuT2cifQ==")); + + } + public void testUnhealthyCluster() throws Exception { String scope = randomBoolean() ? "node" : "kibana"; URL url = new URL(client.getDefaultURL()); @@ -207,10 +241,10 @@ public void testEnrollmentDisabled() { public void testUnableToCreateToken() throws Exception { this.externalEnrollmentTokenGenerator = mock(ExternalEnrollmentTokenGenerator.class); - when(externalEnrollmentTokenGenerator.createKibanaEnrollmentToken(anyString(), any(SecureString.class))).thenThrow( + when(externalEnrollmentTokenGenerator.createKibanaEnrollmentToken(anyString(), any(SecureString.class), any(URL.class))).thenThrow( new IllegalStateException("example exception message") ); - when(externalEnrollmentTokenGenerator.createNodeEnrollmentToken(anyString(), any(SecureString.class))).thenThrow( + when(externalEnrollmentTokenGenerator.createNodeEnrollmentToken(anyString(), any(SecureString.class), any(URL.class))).thenThrow( new IllegalStateException("example exception message") ); String scope = randomBoolean() ? "node" : "kibana";