diff --git a/client/rest-high-level/qa/ssl-enabled/build.gradle b/client/rest-high-level/qa/ssl-enabled/build.gradle
index 164c74e6b292d..8be09ae3b5e80 100644
--- a/client/rest-high-level/qa/ssl-enabled/build.gradle
+++ b/client/rest-high-level/qa/ssl-enabled/build.gradle
@@ -6,6 +6,14 @@
  * Side Public License, v 1.
  */
 
+/*
+ * We need this separate project as tests related to the enrollment process require
+ * test clusters with a specific TLS setup which is also not FIPS 140-2 compliant
+ * (as it uses PKCS#12 keystores). In order to not disable the entire rest-high-level
+ * project when running in fips mode, we moved enrollment tests in this subproject.
+ *
+ */
+
 import org.elasticsearch.gradle.internal.test.RestIntegTestTask
 import org.elasticsearch.gradle.internal.info.BuildParams
 
diff --git a/client/rest-high-level/qa/ssl-enabled/src/javaRestTest/java/org/elasticsearch/client/EnrollmentIT.java b/client/rest-high-level/qa/ssl-enabled/src/javaRestTest/java/org/elasticsearch/client/EnrollmentIT.java
index 5266db022bd4a..6940035fc72a5 100644
--- a/client/rest-high-level/qa/ssl-enabled/src/javaRestTest/java/org/elasticsearch/client/EnrollmentIT.java
+++ b/client/rest-high-level/qa/ssl-enabled/src/javaRestTest/java/org/elasticsearch/client/EnrollmentIT.java
@@ -25,6 +25,7 @@
 import static org.hamcrest.Matchers.endsWith;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.startsWith;
 
 public class EnrollmentIT  extends ESRestHighLevelClientTestCase {
     private static Path httpTrustStore;
@@ -76,7 +77,7 @@ public void testEnrollKibana() throws Exception {
         assertThat(kibanaResponse, notNullValue());
         assertThat(kibanaResponse.getHttpCa()
             , endsWith("brcNC5xq6YE7C4/06nH7F6le4kE4Uo6c9fpkl4ehOxQxndNLn462tFF+8VBA8IftJ1PPWzqGxLsCTzM6p6w8sa+XhgNYglLfkRjirc="));
-        assertNotNull(kibanaResponse.getPassword());
-        assertThat(kibanaResponse.getPassword().toString().length(), equalTo(14));
+        assertNotNull(kibanaResponse.getTokenValue());
+        assertNotNull(kibanaResponse.getTokenName(), startsWith("enroll-process-token-"));
     }
 }
diff --git a/client/rest-high-level/qa/ssl-enabled/src/javaRestTest/java/org/elasticsearch/client/documentation/EnrollmentDocumentationIT.java b/client/rest-high-level/qa/ssl-enabled/src/javaRestTest/java/org/elasticsearch/client/documentation/EnrollmentDocumentationIT.java
new file mode 100644
index 0000000000000..9511df7a4fd03
--- /dev/null
+++ b/client/rest-high-level/qa/ssl-enabled/src/javaRestTest/java/org/elasticsearch/client/documentation/EnrollmentDocumentationIT.java
@@ -0,0 +1,138 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.client.documentation;
+
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.LatchedActionListener;
+import org.elasticsearch.client.ESRestHighLevelClientTestCase;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.security.KibanaEnrollmentResponse;
+import org.elasticsearch.client.security.NodeEnrollmentResponse;
+import org.elasticsearch.common.settings.SecureString;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.util.concurrent.ThreadContext;
+import org.elasticsearch.core.PathUtils;
+import org.junit.BeforeClass;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.Matchers.startsWith;
+
+public class EnrollmentDocumentationIT extends ESRestHighLevelClientTestCase {
+    static Path HTTP_TRUSTSTORE;
+
+    @BeforeClass
+    public static void getResources() throws Exception {
+        HTTP_TRUSTSTORE = PathUtils.get(EnrollmentDocumentationIT.class.getResource("/httpCa.p12").toURI());
+    }
+
+    @Override
+    protected String getProtocol() {
+        return "https";
+    }
+
+    @Override
+    protected Settings restClientSettings() {
+        String token = basicAuthHeaderValue("admin_user", new SecureString("admin-password".toCharArray()));
+
+        return Settings.builder()
+            .put(ThreadContext.PREFIX + ".Authorization", token)
+            .put(TRUSTSTORE_PATH, HTTP_TRUSTSTORE)
+            .put(TRUSTSTORE_PASSWORD, "password")
+            .build();
+    }
+
+    public void testNodeEnrollment() throws Exception {
+        RestHighLevelClient client = highLevelClient();
+
+        {
+            // tag::node-enrollment-execute
+            NodeEnrollmentResponse response = client.security().enrollNode(RequestOptions.DEFAULT);
+            // end::node-enrollment-execute
+
+            // tag::node-enrollment-response
+            String httpCaKey = response.getHttpCaKey(); // <1>
+            String httpCaCert = response.getHttpCaCert(); // <2>
+            String transportKey = response.getTransportKey(); // <3>
+            String transportCert = response.getTransportCert(); // <4>
+            List<String> nodesAddresses = response.getNodesAddresses();  // <5>
+            // end::node-enrollment-response
+        }
+
+        {
+            // tag::node-enrollment-execute-listener
+            ActionListener<NodeEnrollmentResponse> listener =
+                new ActionListener<NodeEnrollmentResponse>() {
+                    @Override
+                    public void onResponse(NodeEnrollmentResponse response) {
+                        // <1>
+                    }
+
+                    @Override
+                    public void onFailure(Exception e) {
+                        // <2>
+                    }};
+            // end::node-enrollment-execute-listener
+
+            final CountDownLatch latch = new CountDownLatch(1);
+            listener = new LatchedActionListener<>(listener, latch);
+
+            // tag::node-enrollment-execute-async
+            client.security().enrollNodeAsync(RequestOptions.DEFAULT, listener);
+            // end::node-enrollment-execute-async
+            assertTrue(latch.await(30L, TimeUnit.SECONDS));
+        }
+    }
+
+    public void testKibanaEnrollment() throws Exception {
+        RestHighLevelClient client = highLevelClient();
+
+        {
+            // tag::kibana-enrollment-execute
+            KibanaEnrollmentResponse response = client.security().enrollKibana(RequestOptions.DEFAULT);
+            // end::kibana-enrollment-execute
+
+            // tag::kibana-enrollment-response
+            String tokenName = response.getTokenName(); // <1>
+            SecureString tokenValue = response.getTokenValue(); // <2>
+            String httoCa = response.getHttpCa(); // <3>
+            // end::kibana-enrollment-response
+            assertNotNull(tokenValue);
+            assertThat(tokenName, startsWith("enroll-process-token-"));
+        }
+
+        {
+            // tag::kibana-enrollment-execute-listener
+            ActionListener<KibanaEnrollmentResponse> listener =
+                new ActionListener<KibanaEnrollmentResponse>() {
+                    @Override
+                    public void onResponse(KibanaEnrollmentResponse response) {
+                        // <1>
+                    }
+
+                    @Override
+                    public void onFailure(Exception e) {
+                        // <2>
+                    }};
+            // end::kibana-enrollment-execute-listener
+
+            final CountDownLatch latch = new CountDownLatch(1);
+            listener = new LatchedActionListener<>(listener, latch);
+
+            // tag::kibana-enrollment-execute-async
+            client.security().enrollKibanaAsync(RequestOptions.DEFAULT, listener);
+            // end::kibana-enrollment-execute-async
+            assertTrue(latch.await(30L, TimeUnit.SECONDS));
+        }
+    }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/KibanaEnrollmentResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/KibanaEnrollmentResponse.java
index b9e71f2a08ed6..56604d849ed1d 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/KibanaEnrollmentResponse.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/KibanaEnrollmentResponse.java
@@ -16,34 +16,51 @@
 import java.io.IOException;
 import java.util.Objects;
 
+import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
+
 public final class KibanaEnrollmentResponse {
 
-    private SecureString password;
+    private String tokenName;
+    private SecureString tokenValue;
     private String httpCa;
 
-    public KibanaEnrollmentResponse(SecureString password, String httpCa) {
-        this.password = password;
+    public KibanaEnrollmentResponse(String tokenName, SecureString tokenValue, String httpCa) {
+        this.tokenName = tokenName;
+        this.tokenValue = tokenValue;
         this.httpCa = httpCa;
     }
 
-    public SecureString getPassword() { return password; }
+    public String getTokenName() { return tokenName; }
+
+    public SecureString getTokenValue() { return tokenValue; }
 
     public String getHttpCa() {
         return httpCa;
     }
 
-    private static final ParseField PASSWORD = new ParseField("password");
+    private static final ParseField TOKEN = new ParseField("token");
+    private static final ParseField TOKEN_NAME = new ParseField("name");
+    private static final ParseField TOKEN_VALUE = new ParseField("value");
     private static final ParseField HTTP_CA = new ParseField("http_ca");
 
-    @SuppressWarnings("unchecked")
+    static final ConstructingObjectParser<Token, Void> TOKEN_PARSER = new ConstructingObjectParser<>(
+        KibanaEnrollmentResponse.class.getName(), true,
+        a -> new Token((String) a[0], (String) a[1])
+    );
+
     private static final ConstructingObjectParser<KibanaEnrollmentResponse, Void> PARSER =
         new ConstructingObjectParser<>(
             KibanaEnrollmentResponse.class.getName(), true,
-            a -> new KibanaEnrollmentResponse(new SecureString(((String) a[0]).toCharArray()), (String) a[1]));
+            a -> {
+                final Token token = (Token) a[0];
+                return new KibanaEnrollmentResponse(token.name, new SecureString(token.value.toCharArray()), (String) a[1]);
+            });
 
     static {
-        PARSER.declareString(ConstructingObjectParser.constructorArg(), PASSWORD);
-        PARSER.declareString(ConstructingObjectParser.constructorArg(), HTTP_CA);
+        TOKEN_PARSER.declareString(constructorArg(), TOKEN_NAME);
+        TOKEN_PARSER.declareString(constructorArg(), TOKEN_VALUE);
+        PARSER.declareObject(constructorArg(), TOKEN_PARSER, TOKEN);
+        PARSER.declareString(constructorArg(), HTTP_CA);
     }
 
     public static KibanaEnrollmentResponse fromXContent(XContentParser parser) throws IOException {
@@ -54,10 +71,20 @@ public static KibanaEnrollmentResponse fromXContent(XContentParser parser) throw
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         KibanaEnrollmentResponse that = (KibanaEnrollmentResponse) o;
-        return password.equals(that.password) && httpCa.equals(that.httpCa);
+        return tokenName.equals(that.tokenName) && tokenValue.equals(that.tokenValue) && httpCa.equals(that.httpCa);
     }
 
     @Override public int hashCode() {
-        return Objects.hash(password, httpCa);
+        return Objects.hash(tokenName, tokenValue, httpCa);
+    }
+
+    private static class Token {
+        private final String name;
+        private final String value;
+
+        Token(String name, String value) {
+            this.name = name;
+            this.value = value;
+        }
     }
 }
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java
index 153e412296e5a..6a463926d4a43 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java
@@ -75,7 +75,6 @@
 import org.elasticsearch.client.security.InvalidateApiKeyResponse;
 import org.elasticsearch.client.security.InvalidateTokenRequest;
 import org.elasticsearch.client.security.InvalidateTokenResponse;
-import org.elasticsearch.client.security.NodeEnrollmentResponse;
 import org.elasticsearch.client.security.PutPrivilegesRequest;
 import org.elasticsearch.client.security.PutPrivilegesResponse;
 import org.elasticsearch.client.security.PutRoleMappingRequest;
@@ -103,7 +102,6 @@
 import org.elasticsearch.client.security.user.privileges.Role.ClusterPrivilegeName;
 import org.elasticsearch.client.security.user.privileges.Role.IndexPrivilegeName;
 import org.elasticsearch.client.security.user.privileges.UserIndicesPrivileges;
-import org.elasticsearch.client.security.KibanaEnrollmentResponse;
 import org.elasticsearch.core.CheckedConsumer;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.settings.SecureString;
@@ -3008,90 +3006,6 @@ public void onFailure(Exception e) {
         }
     }
 
-    @AwaitsFix(bugUrl = "Determine behavior for keystores with multiple keys")
-    public void testNodeEnrollment() throws Exception {
-        RestHighLevelClient client = highLevelClient();
-
-        {
-            // tag::node-enrollment-execute
-            NodeEnrollmentResponse response = client.security().enrollNode(RequestOptions.DEFAULT);
-            // end::node-enrollment-execute
-
-            // tag::node-enrollment-response
-            String httpCaKey = response.getHttpCaKey(); // <1>
-            String httpCaCert = response.getHttpCaCert(); // <2>
-            String transportKey = response.getTransportKey(); // <3>
-            String transportCert = response.getTransportCert(); // <4>
-            List<String> nodesAddresses = response.getNodesAddresses();  // <5>
-            // end::node-enrollment-response
-        }
-
-        {
-            // tag::node-enrollment-execute-listener
-            ActionListener<NodeEnrollmentResponse> listener =
-                new ActionListener<NodeEnrollmentResponse>() {
-                    @Override
-                    public void onResponse(NodeEnrollmentResponse response) {
-                        // <1>
-                    }
-
-                    @Override
-                    public void onFailure(Exception e) {
-                        // <2>
-                    }};
-            // end::node-enrollment-execute-listener
-
-            final CountDownLatch latch = new CountDownLatch(1);
-            listener = new LatchedActionListener<>(listener, latch);
-
-            // tag::node-enrollment-execute-async
-            client.security().enrollNodeAsync(RequestOptions.DEFAULT, listener);
-            // end::node-enrollment-execute-async
-            assertTrue(latch.await(30L, TimeUnit.SECONDS));
-        }
-    }
-
-    @AwaitsFix(bugUrl = "Determine behavior for keystores with multiple keys")
-    public void testKibanaEnrollment() throws Exception {
-        RestHighLevelClient client = highLevelClient();
-
-        {
-            // tag::kibana-enrollment-execute
-            KibanaEnrollmentResponse response = client.security().enrollKibana(RequestOptions.DEFAULT);
-            // end::kibana-enrollment-execute
-
-            // tag::kibana-enrollment-response
-            SecureString password = response.getPassword(); // <1>
-            String httoCa = response.getHttpCa(); // <2>
-            // end::kibana-enrollment-response
-            assertThat(password.length(), equalTo(14));
-        }
-
-        {
-            // tag::kibana-enrollment-execute-listener
-            ActionListener<KibanaEnrollmentResponse> listener =
-                new ActionListener<KibanaEnrollmentResponse>() {
-                    @Override
-                    public void onResponse(KibanaEnrollmentResponse response) {
-                        // <1>
-                    }
-
-                    @Override
-                    public void onFailure(Exception e) {
-                        // <2>
-                    }};
-            // end::kibana-enrollment-execute-listener
-
-            final CountDownLatch latch = new CountDownLatch(1);
-            listener = new LatchedActionListener<>(listener, latch);
-
-            // tag::kibana-enrollment-execute-async
-            client.security().enrollKibanaAsync(RequestOptions.DEFAULT, listener);
-            // end::kibana-enrollment-execute-async
-            assertTrue(latch.await(30L, TimeUnit.SECONDS));
-        }
-    }
-
     private X509Certificate readCertForPkiDelegation(String certificateName) throws Exception {
         Path path = getDataPath("/org/elasticsearch/client/security/delegate_pki/" + certificateName);
         try (InputStream in = Files.newInputStream(path)) {
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/KibanaEnrollmentResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/KibanaEnrollmentResponseTests.java
new file mode 100644
index 0000000000000..35d5453e798da
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/KibanaEnrollmentResponseTests.java
@@ -0,0 +1,91 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.client.security;
+
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.settings.SecureString;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.test.EqualsHashCodeTestUtils;
+
+import java.io.IOException;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class KibanaEnrollmentResponseTests extends ESTestCase {
+
+    public void testFromXContent() throws IOException {
+        final String tokenName = randomAlphaOfLengthBetween(8 ,14);
+        final String tokenValue = randomAlphaOfLengthBetween(58, 70);
+        final String httpCa = randomAlphaOfLength(50);
+
+        final XContentType xContentType = randomFrom(XContentType.values());
+        final XContentBuilder builder = XContentFactory.contentBuilder(xContentType);
+        builder.startObject()
+            .startObject("token")
+            .field("name", tokenName)
+            .field("value", tokenValue)
+            .endObject()
+            .field("http_ca", httpCa)
+            .endObject();
+        BytesReference xContent = BytesReference.bytes(builder);
+
+        final KibanaEnrollmentResponse response = KibanaEnrollmentResponse.fromXContent(createParser(xContentType.xContent(), xContent));
+        assertThat(response.getTokenName(), equalTo(tokenName));
+        assertThat(response.getTokenValue(), equalTo(tokenValue));
+        assertThat(response.getHttpCa(), equalTo(httpCa));
+    }
+
+    public void testEqualsHashCode() {
+        final String tokenName = randomAlphaOfLengthBetween(8 ,14);
+        final SecureString tokenValue = new SecureString(randomAlphaOfLengthBetween(58, 70).toCharArray());
+        final String httpCa = randomAlphaOfLength(50);
+        KibanaEnrollmentResponse kibanaEnrollmentResponse = new KibanaEnrollmentResponse(tokenName, tokenValue, httpCa);
+
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(kibanaEnrollmentResponse,
+            (original) -> new KibanaEnrollmentResponse(original.getTokenName(), original.getTokenValue(), original.getHttpCa()));
+
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(kibanaEnrollmentResponse,
+            (original) -> new KibanaEnrollmentResponse(original.getTokenName(), original.getTokenValue(), original.getHttpCa()),
+            KibanaEnrollmentResponseTests::mutateTestItem);
+    }
+
+    private static KibanaEnrollmentResponse mutateTestItem(KibanaEnrollmentResponse original) {
+        switch (randomIntBetween(0, 3)) {
+            case 0:
+                return new KibanaEnrollmentResponse(
+                    randomAlphaOfLengthBetween(14, 20),
+                    new SecureString(randomAlphaOfLengthBetween(71, 90).toCharArray()),
+                    randomAlphaOfLength(52)
+                );
+            case 1:
+                return new KibanaEnrollmentResponse(
+                    original.getTokenName(),
+                    new SecureString(randomAlphaOfLengthBetween(71, 90).toCharArray()),
+                    randomAlphaOfLength(52)
+                );
+            case 2:
+                return new KibanaEnrollmentResponse(
+                    randomAlphaOfLengthBetween(14, 20),
+                    original.getTokenValue(),
+                    randomAlphaOfLength(52)
+                );
+            case 3:
+                return new KibanaEnrollmentResponse(
+                    randomAlphaOfLengthBetween(14, 20),
+                    new SecureString(randomAlphaOfLengthBetween(71, 90).toCharArray()),
+                    original.getHttpCa()
+                );
+        }
+        // we never reach here
+        return null;
+    }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/KibanaErnollmentResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/KibanaErnollmentResponseTests.java
deleted file mode 100644
index 937e750ccb72c..0000000000000
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/KibanaErnollmentResponseTests.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.security;
-
-import org.elasticsearch.common.bytes.BytesReference;
-import org.elasticsearch.common.settings.SecureString;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentFactory;
-import org.elasticsearch.common.xcontent.XContentType;
-import org.elasticsearch.test.ESTestCase;
-import org.elasticsearch.test.EqualsHashCodeTestUtils;
-
-import java.io.IOException;
-import java.util.List;
-
-import static org.hamcrest.Matchers.equalTo;
-
-public class KibanaErnollmentResponseTests extends ESTestCase {
-
-    public void testFromXContent() throws IOException {
-        final String password = randomAlphaOfLength(14);
-        final String httpCa = randomAlphaOfLength(50);
-        final List<String> nodesAddresses = randomList(2, 10, () -> buildNewFakeTransportAddress().toString());
-
-        final XContentType xContentType = randomFrom(XContentType.values());
-        final XContentBuilder builder = XContentFactory.contentBuilder(xContentType);
-        builder.startObject().field("password", password).field("http_ca", httpCa).field("nodes_addresses", nodesAddresses).endObject();
-        BytesReference xContent = BytesReference.bytes(builder);
-
-        final KibanaEnrollmentResponse response = KibanaEnrollmentResponse.fromXContent(createParser(xContentType.xContent(), xContent));
-        assertThat(response.getPassword(), equalTo(password));
-        assertThat(response.getHttpCa(), equalTo(httpCa));
-    }
-
-    public void testEqualsHashCode() {
-        final SecureString password = new SecureString(randomAlphaOfLength(14).toCharArray());
-        final String httpCa = randomAlphaOfLength(50);
-        KibanaEnrollmentResponse kibanaEnrollmentResponse = new KibanaEnrollmentResponse(password, httpCa);
-
-        EqualsHashCodeTestUtils.checkEqualsAndHashCode(kibanaEnrollmentResponse,
-            (original) -> new KibanaEnrollmentResponse(original.getPassword(), original.getHttpCa()));
-
-        EqualsHashCodeTestUtils.checkEqualsAndHashCode(kibanaEnrollmentResponse,
-            (original) -> new KibanaEnrollmentResponse(original.getPassword(), original.getHttpCa()),
-            KibanaErnollmentResponseTests::mutateTestItem);
-    }
-
-    private static KibanaEnrollmentResponse mutateTestItem(KibanaEnrollmentResponse original) {
-        switch (randomIntBetween(0, 1)) {
-            case 0:
-                return new KibanaEnrollmentResponse(new SecureString(randomAlphaOfLength(14).toCharArray()),
-                    original.getHttpCa());
-            case 1:
-                return new KibanaEnrollmentResponse(original.getPassword(), randomAlphaOfLength(51));
-            default:
-                return new KibanaEnrollmentResponse(original.getPassword(),
-                    original.getHttpCa());
-        }
-    }
-}
diff --git a/docs/java-rest/high-level/security/enroll_kibana.asciidoc b/docs/java-rest/high-level/security/enroll_kibana.asciidoc
index 6e9111375b9bf..c6a7da354d066 100644
--- a/docs/java-rest/high-level/security/enroll_kibana.asciidoc
+++ b/docs/java-rest/high-level/security/enroll_kibana.asciidoc
@@ -19,11 +19,15 @@ executed operation as follows:
 
 ["source","java",subs="attributes,callouts,macros"]
 --------------------------------------------------
-include-tagged::{doc-tests-file}[{api-kibana-response]
+include-tagged::{doc-tests}/EnrollmentDocumentationIT.java[{api}-response]
 --------------------------------------------------
-<1> The password for the `kibana_system` user
-<2> The CA certificate that has signed the certificate that the cluster uses for TLS on the HTTP layer,
-as a Base64 encoded string of the ASN.1 DER encoding of the certificate.
+<1> The bearer token for the `elastic/kibana` service account.
+Use this token to {ref}/service-accounts.html#authenticate-with-service-account-token[authenticate the service account] with {es}.
+<2> The value of the bearer token for the `elastic/kibana` service account.
+<3> The CA certificate used to sign the node certificates that {es} uses for TLS
+on the HTTP layer. The certificate is returned as a Base64 encoded string of the
+ASN.1 DER encoding of the certificate.
+
 
 [id="{upid}-{api}-execute-async"]
 ==== Asynchronous Execution
@@ -33,14 +37,14 @@ method:
 
 ["source","java",subs="attributes,callouts,macros"]
 --------------------------------------------------
-include-tagged::{doc-tests-file}[{api}-execute-async]
+include-tagged::{doc-tests}/EnrollmentDocumentationIT.java[{api}-execute-async]
 --------------------------------------------------
 
 A typical listener for a `KibanaEnrollmentResponse` looks like:
 
 ["source","java",subs="attributes,callouts,macros"]
 --------------------------------------------------
-include-tagged::{doc-tests-file}[{api}-execute-listener]
+include-tagged::{doc-tests}/EnrollmentDocumentationIT.java[{api}-execute-listener]
 --------------------------------------------------
 <1> Called when the execution is successfully completed. The response is
 provided as an argument
diff --git a/docs/java-rest/high-level/cluster/enroll_node.asciidoc b/docs/java-rest/high-level/security/enroll_node.asciidoc
similarity index 91%
rename from docs/java-rest/high-level/cluster/enroll_node.asciidoc
rename to docs/java-rest/high-level/security/enroll_node.asciidoc
index e8bdaef30850f..374e2d46a8b41 100644
--- a/docs/java-rest/high-level/cluster/enroll_node.asciidoc
+++ b/docs/java-rest/high-level/security/enroll_node.asciidoc
@@ -27,7 +27,7 @@ executed operation as follows:
 
 ["source","java",subs="attributes,callouts,macros"]
 --------------------------------------------------
-include-tagged::{doc-tests-file}[{api}-response]
+include-tagged::{doc-tests}/EnrollmentDocumentationIT.java[{api}-response]
 --------------------------------------------------
 <1> The CA private key that can be used by the new node in order to sign its certificate
 for the HTTP layer, as a Base64 encoded string of the ASN.1 DER encoding of the key.
@@ -49,14 +49,14 @@ method:
 
 ["source","java",subs="attributes,callouts,macros"]
 --------------------------------------------------
-include-tagged::{doc-tests-file}[{api}-execute-async]
+include-tagged::{doc-tests}/EnrollmentDocumentationIT.java[{api}-execute-async]
 --------------------------------------------------
 
 A typical listener for a `NodeEnrollmentResponse` looks like:
 
 ["source","java",subs="attributes,callouts,macros"]
 --------------------------------------------------
-include-tagged::{doc-tests-file}[{api}-execute-listener]
+include-tagged::{doc-tests}/EnrollmentDocumentationIT.java[{api}-execute-listener]
 --------------------------------------------------
 <1> Called when the execution is successfully completed. The response is
 provided as an argument
diff --git a/x-pack/docs/en/rest-api/security.asciidoc b/x-pack/docs/en/rest-api/security.asciidoc
index 09b244fe32d00..e023094ef8d2a 100644
--- a/x-pack/docs/en/rest-api/security.asciidoc
+++ b/x-pack/docs/en/rest-api/security.asciidoc
@@ -140,7 +140,6 @@ include::security/clear-privileges-cache.asciidoc[]
 include::security/clear-api-key-cache.asciidoc[]
 include::security/clear-service-token-caches.asciidoc[]
 include::security/create-api-keys.asciidoc[]
-include::security/enroll-kibana.asciidoc[]
 include::security/put-app-privileges.asciidoc[]
 include::security/create-role-mappings.asciidoc[]
 include::security/create-roles.asciidoc[]
@@ -154,6 +153,7 @@ include::security/delete-service-token.asciidoc[]
 include::security/delete-users.asciidoc[]
 include::security/disable-users.asciidoc[]
 include::security/enable-users.asciidoc[]
+include::security/enroll-kibana.asciidoc[]
 include::security/enroll-node.asciidoc[]
 include::security/get-api-keys.asciidoc[]
 include::security/get-app-privileges.asciidoc[]
diff --git a/x-pack/docs/en/rest-api/security/enroll-kibana.asciidoc b/x-pack/docs/en/rest-api/security/enroll-kibana.asciidoc
index 0736900ce2104..55de31b5407d1 100644
--- a/x-pack/docs/en/rest-api/security/enroll-kibana.asciidoc
+++ b/x-pack/docs/en/rest-api/security/enroll-kibana.asciidoc
@@ -35,10 +35,16 @@ The API returns the following response:
 [source,console_result]
 ----
 {
-  "password" : "longsecurepassword", <1>
-  "http_ca" : "MIIJlAIBAzCCCVoGCSqGSIb3....vsDfsA3UZBAjEPfhubpQysAICCAA=", <2>
+  "token" : {
+    "name" : "enroll-process-token-1629123923000", <1>
+    "value": "AAEAAWVsYXN0aWM...vZmxlZXQtc2VydmVyL3Rva2VuMTo3TFdaSDZ" <2>
+  },
+  "http_ca" : "MIIJlAIBAzVoGCSqGSIb3...vsDfsA3UZBAjEPfhubpQysAICAA=", <3>
 }
 ----
-<1> The password for the `kibana_system` user.
-<2> The CA certificate used to sign the node certificates that {es} uses for TLS on the HTTP layer.
-The certificate is returned as a Base64 encoded string of the ASN.1 DER encoding of the certificate.
+<1> The name of the bearer token for the `elastic/kibana` service account.
+<2> The value of the bearer token for the `elastic/kibana` service account.
+Use this value to {ref}/service-accounts.html#authenticate-with-service-account-token[authenticate the service account] with {es}.
+<3> The CA certificate used to sign the node certificates that {es} uses for TLS
+on the HTTP layer. The certificate is returned as a Base64 encoded string of the
+ASN.1 DER encoding of the certificate.
diff --git a/x-pack/docs/en/rest-api/security/enroll-node.asciidoc b/x-pack/docs/en/rest-api/security/enroll-node.asciidoc
index d7d41d71f2367..a6a876b9d98c0 100644
--- a/x-pack/docs/en/rest-api/security/enroll-node.asciidoc
+++ b/x-pack/docs/en/rest-api/security/enroll-node.asciidoc
@@ -1,7 +1,7 @@
 [[security-api-node-enrollment]]
 === Enroll Node API
 ++++
-<titleabbrev>Enroll Node</titleabbrev>
+<titleabbrev>Enroll node</titleabbrev>
 ++++
 
 Allows a new node to join an existing cluster with security features enabled.
diff --git a/x-pack/docs/en/security/authentication/service-accounts.asciidoc b/x-pack/docs/en/security/authentication/service-accounts.asciidoc
index 6964d2e0785d6..67cd98e1a1df2 100644
--- a/x-pack/docs/en/security/authentication/service-accounts.asciidoc
+++ b/x-pack/docs/en/security/authentication/service-accounts.asciidoc
@@ -29,7 +29,9 @@ traditional roles
 
 Service accounts are not included in the response of the
 <<security-api-get-user,get users API>>. To retrieve a service account, use the
-<<security-api-get-service-accounts,get service accounts API>>.
+<<security-api-get-service-accounts,get service accounts API>>. Use the
+<<security-api-get-service-credentials,get service account credentials API>>
+to retrieve all service credentials for a service account.
 
 [discrete]
 [[service-accounts-explanation]]
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/enrollment/KibanaEnrollmentResponse.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/enrollment/KibanaEnrollmentResponse.java
index bad9b0fdb678d..5e35355a70869 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/enrollment/KibanaEnrollmentResponse.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/enrollment/KibanaEnrollmentResponse.java
@@ -11,75 +11,61 @@
 import org.elasticsearch.common.io.stream.StreamInput;
 import org.elasticsearch.common.io.stream.StreamOutput;
 import org.elasticsearch.common.settings.SecureString;
-import org.elasticsearch.common.xcontent.ConstructingObjectParser;
-import org.elasticsearch.common.xcontent.ParseField;
 import org.elasticsearch.common.xcontent.ToXContentObject;
 import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentParser;
-
 import java.io.IOException;
 import java.util.Objects;
 
 public final class KibanaEnrollmentResponse extends ActionResponse implements ToXContentObject {
 
-    private static final ParseField PASSWORD = new ParseField("password");
-    private static final ParseField HTTP_CA = new ParseField("http_ca");
-
-    @SuppressWarnings("unchecked")
-    private static final ConstructingObjectParser<KibanaEnrollmentResponse, Void> PARSER =
-        new ConstructingObjectParser<>(
-            KibanaEnrollmentResponse.class.getName(), true,
-            a -> new KibanaEnrollmentResponse(new SecureString(((String) a[0]).toCharArray()), (String) a[1]));
-
-    static {
-        PARSER.declareString(ConstructingObjectParser.constructorArg(), PASSWORD);
-        PARSER.declareString(ConstructingObjectParser.constructorArg(), HTTP_CA);
-    }
-
-    private final SecureString password;
+    private final String tokenName;
+    private final SecureString tokenValue;
     private final String httpCa;
 
     public KibanaEnrollmentResponse(StreamInput in) throws IOException {
         super(in);
-        password = in.readSecureString();
+        tokenName = in.readString();
+        tokenValue = in.readSecureString();
         httpCa = in.readString();
     }
 
-    public KibanaEnrollmentResponse(SecureString password, String httpCa) {
-        this.password = password;
+    public KibanaEnrollmentResponse(String tokenName, SecureString tokenValue, String httpCa) {
+        this.tokenName = tokenName;
+        this.tokenValue = tokenValue;
         this.httpCa = httpCa;
     }
 
-    public SecureString getPassword() { return password; }
+    public String getTokenName() { return tokenName; }
+    public SecureString getTokenValue() { return tokenValue; }
     public String getHttpCa() {
         return httpCa;
     }
 
-    @Override public XContentBuilder toXContent(
-        XContentBuilder builder, Params params) throws IOException {
-        builder.startObject();
-        builder.field(PASSWORD.getPreferredName(), password.toString());
-        builder.field(HTTP_CA.getPreferredName(), httpCa);
-        return builder.endObject();
-    }
-
     @Override public void writeTo(StreamOutput out) throws IOException {
-        out.writeSecureString(password);
+        out.writeString(tokenName);
+        out.writeSecureString(tokenValue);
         out.writeString(httpCa);
     }
 
-    public static KibanaEnrollmentResponse fromXContent(XContentParser parser) {
-        return PARSER.apply(parser, null);
-    }
-
     @Override public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-        KibanaEnrollmentResponse response = (KibanaEnrollmentResponse) o;
-        return password.equals(response.password) && httpCa.equals(response.httpCa);
+        KibanaEnrollmentResponse that = (KibanaEnrollmentResponse) o;
+        return tokenName.equals(that.tokenName) && tokenValue.equals(that.tokenValue) && httpCa.equals(that.httpCa);
     }
 
     @Override public int hashCode() {
-        return Objects.hash(password, httpCa);
+        return Objects.hash(tokenName, tokenValue, httpCa);
+    }
+
+    @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+        builder.startObject()
+            .startObject("token")
+            .field("name", tokenName)
+            .field("value", tokenValue.toString())
+            .endObject()
+            .field("http_ca", httpCa)
+            .endObject();
+        return builder;
     }
 }
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/enrollment/KibanaEnrollmentResponseTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/enrollment/KibanaEnrollmentResponseTests.java
index 1868a2365a121..ac56dd0c87009 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/enrollment/KibanaEnrollmentResponseTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/enrollment/KibanaEnrollmentResponseTests.java
@@ -7,41 +7,81 @@
 
 package org.elasticsearch.xpack.core.security.action.enrollment;
 
-import org.elasticsearch.common.io.stream.BytesStreamOutput;
-import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.io.stream.Writeable;
 import org.elasticsearch.common.settings.SecureString;
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractXContentTestCase;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentHelper;
+import org.elasticsearch.test.AbstractWireSerializingTestCase;
 
 import java.io.IOException;
+import java.util.Map;
 
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.equalTo;
 
-public class KibanaEnrollmentResponseTests extends AbstractXContentTestCase<KibanaEnrollmentResponse> {
+public class KibanaEnrollmentResponseTests extends AbstractWireSerializingTestCase<KibanaEnrollmentResponse> {
 
-    @Override protected KibanaEnrollmentResponse createTestInstance() {
-        return new KibanaEnrollmentResponse(
-            new SecureString(randomAlphaOfLength(14).toCharArray()),
-            randomAlphaOfLength(50));
-    }
 
-    @Override protected KibanaEnrollmentResponse doParseInstance(XContentParser parser) throws IOException {
-        return KibanaEnrollmentResponse.fromXContent(parser);
+    @Override
+    protected Writeable.Reader<KibanaEnrollmentResponse> instanceReader() {
+        return KibanaEnrollmentResponse::new;
     }
 
-    @Override protected boolean supportsUnknownFields() {
-        return false;
+    @Override
+    protected KibanaEnrollmentResponse createTestInstance() {
+        return new KibanaEnrollmentResponse(
+            randomAlphaOfLengthBetween(8, 12),
+            new SecureString(randomAlphaOfLengthBetween(58, 70).toCharArray()),
+            randomAlphaOfLength(50)
+        );
     }
 
-    public void testSerialization() throws IOException{
-        KibanaEnrollmentResponse response = createTestInstance();
-        try (BytesStreamOutput out = new BytesStreamOutput()) {
-            response.writeTo(out);
-            try (StreamInput in = out.bytes().streamInput()) {
-                KibanaEnrollmentResponse serialized = new KibanaEnrollmentResponse(in);
-                assertThat(response.getHttpCa(), is(serialized.getHttpCa()));
-                assertThat(response.getPassword(), is(serialized.getPassword()));
-            }
+    @Override
+    protected KibanaEnrollmentResponse mutateInstance(KibanaEnrollmentResponse instance) throws IOException {
+        switch (randomIntBetween(0, 3)) {
+            case 0:
+                return new KibanaEnrollmentResponse(
+                    randomAlphaOfLengthBetween(14, 20),
+                    new SecureString(randomAlphaOfLengthBetween(71, 90).toCharArray()),
+                    randomAlphaOfLength(52)
+                );
+            case 1:
+                return new KibanaEnrollmentResponse(
+                    instance.getTokenName(),
+                    new SecureString(randomAlphaOfLengthBetween(71, 90).toCharArray()),
+                    randomAlphaOfLength(52)
+                );
+            case 2:
+                return new KibanaEnrollmentResponse(
+                    randomAlphaOfLengthBetween(14, 20),
+                    instance.getTokenValue(),
+                    randomAlphaOfLength(52)
+                );
+            case 3:
+                return new KibanaEnrollmentResponse(
+                    randomAlphaOfLengthBetween(14, 20),
+                    new SecureString(randomAlphaOfLengthBetween(71, 90).toCharArray()),
+                    instance.getHttpCa()
+                );
         }
+        // we never reach here
+        return null;
     }
+
+    public void testToXContent() throws IOException {
+        final KibanaEnrollmentResponse response = createTestInstance();
+        XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
+        response.toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
+        final Map<String, Object> responseMap = XContentHelper.convertToMap(
+            BytesReference.bytes(jsonBuilder),
+            false, jsonBuilder.contentType()).v2();
+
+        assertThat(responseMap, equalTo(Map.of(
+            "token", Map.of("name", response.getTokenName(), "value", response.getTokenValue().toString()),
+            "http_ca", response.getHttpCa()
+        )));
+    }
+
 }
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/enrollment/TransportKibanaEnrollmentAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/enrollment/TransportKibanaEnrollmentAction.java
index 1ca47ab7a8911..ce4c77b2b6528 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/enrollment/TransportKibanaEnrollmentAction.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/enrollment/TransportKibanaEnrollmentAction.java
@@ -16,28 +16,25 @@
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.OriginSettingClient;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.settings.SecureString;
 import org.elasticsearch.core.Tuple;
 import org.elasticsearch.env.Environment;
 import org.elasticsearch.tasks.Task;
 import org.elasticsearch.transport.TransportService;
-import org.elasticsearch.xpack.core.XPackSettings;
 import org.elasticsearch.xpack.core.security.action.enrollment.KibanaEnrollmentAction;
 import org.elasticsearch.xpack.core.security.action.enrollment.KibanaEnrollmentRequest;
 import org.elasticsearch.xpack.core.security.action.enrollment.KibanaEnrollmentResponse;
-import org.elasticsearch.xpack.core.security.action.user.ChangePasswordAction;
-import org.elasticsearch.xpack.core.security.action.user.ChangePasswordRequest;
-import org.elasticsearch.xpack.core.security.action.user.ChangePasswordRequestBuilder;
-import org.elasticsearch.xpack.core.security.authc.support.Hasher;
+import org.elasticsearch.xpack.core.security.action.service.CreateServiceAccountTokenAction;
+import org.elasticsearch.xpack.core.security.action.service.CreateServiceAccountTokenRequest;
 import org.elasticsearch.xpack.core.ssl.KeyConfig;
 import org.elasticsearch.xpack.core.ssl.SSLService;
 import org.elasticsearch.xpack.core.ssl.StoreKeyConfig;
 
 import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN;
 
-import java.security.SecureRandom;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
 import java.util.Base64;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -58,7 +55,6 @@ public class TransportKibanaEnrollmentAction extends HandledTransportAction<Kiba
         ActionFilters actionFilters) {
         super(KibanaEnrollmentAction.NAME, transportService, actionFilters, KibanaEnrollmentRequest::new);
         this.environment = environment;
-        // Should we use a specific origin for this ? Are we satisfied with the auditability of the change password request as-is ?
         this.client = new OriginSettingClient(client, SECURITY_ORIGIN);
         this.sslService = sslService;
     }
@@ -98,28 +94,20 @@ public class TransportKibanaEnrollmentAction extends HandledTransportAction<Kiba
                     cee));
                 return;
             }
-            final char[] password = generateKibanaSystemPassword();
-            final ChangePasswordRequest changePasswordRequest =
-                new ChangePasswordRequestBuilder(client).username("kibana_system")
-                    .password(password.clone(), Hasher.resolve(XPackSettings.PASSWORD_HASHING_ALGORITHM.get(environment.settings())))
-                    .request();
-            client.execute(ChangePasswordAction.INSTANCE, changePasswordRequest, ActionListener.wrap(response -> {
-                logger.debug("Successfully set the password for user [kibana_system] during kibana enrollment");
-                listener.onResponse(new KibanaEnrollmentResponse(new SecureString(password), httpCa));
-            }, e -> listener.onFailure(new ElasticsearchException("Failed to set the password for user [kibana_system]", e))));
+            final CreateServiceAccountTokenRequest createServiceAccountTokenRequest =
+                new CreateServiceAccountTokenRequest("elastic", "kibana", getTokenName());
+            client.execute(CreateServiceAccountTokenAction.INSTANCE, createServiceAccountTokenRequest, ActionListener.wrap(response -> {
+                logger.debug("Successfully created token [{}] for the [elastic/kibana] service account during kibana enrollment",
+                    response.getName());
+                listener.onResponse(new KibanaEnrollmentResponse(response.getName(), response.getValue(), httpCa));
+            }, e -> listener.onFailure(
+                new ElasticsearchException("Failed to create token for the [elastic/kibana] service account", e))));
         }
-
     }
 
-    private char[] generateKibanaSystemPassword() {
-        final char[] passwordChars = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*-_=+?").toCharArray();
-        final SecureRandom secureRandom = new SecureRandom();
-        int passwordLength = 14;
-        char[] characters = new char[passwordLength];
-        for (int i = 0; i < passwordLength; ++i) {
-            characters[i] = passwordChars[secureRandom.nextInt(passwordChars.length)];
-        }
-        return characters;
+    protected static String getTokenName(){
+        final ZonedDateTime enrollTime = ZonedDateTime.now(ZoneOffset.UTC);
+        final String prefix = "enroll-process-token-";
+        return prefix + enrollTime.toInstant().toEpochMilli();
     }
-
 }
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/enrollment/TransportKibanaEnrollmentActionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/enrollment/TransportKibanaEnrollmentActionTests.java
index fdfedc7acfabc..106f16687d753 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/enrollment/TransportKibanaEnrollmentActionTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/enrollment/TransportKibanaEnrollmentActionTests.java
@@ -9,12 +9,11 @@
 
 import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.action.ActionListener;
-import org.elasticsearch.action.ActionResponse;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.PlainActionFuture;
 import org.elasticsearch.client.Client;
-import org.elasticsearch.client.ValidationException;
 import org.elasticsearch.common.settings.MockSecureSettings;
+import org.elasticsearch.common.settings.SecureString;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.util.concurrent.ThreadContext;
 import org.elasticsearch.env.Environment;
@@ -25,8 +24,9 @@
 import org.elasticsearch.transport.TransportService;
 import org.elasticsearch.xpack.core.security.action.enrollment.KibanaEnrollmentRequest;
 import org.elasticsearch.xpack.core.security.action.enrollment.KibanaEnrollmentResponse;
-import org.elasticsearch.xpack.core.security.action.user.ChangePasswordAction;
-import org.elasticsearch.xpack.core.security.action.user.ChangePasswordRequest;
+import org.elasticsearch.xpack.core.security.action.service.CreateServiceAccountTokenAction;
+import org.elasticsearch.xpack.core.security.action.service.CreateServiceAccountTokenRequest;
+import org.elasticsearch.xpack.core.security.action.service.CreateServiceAccountTokenResponse;
 import org.elasticsearch.xpack.core.ssl.SSLConfiguration;
 import org.elasticsearch.xpack.core.ssl.SSLService;
 import org.junit.Before;
@@ -48,9 +48,11 @@
 import static org.mockito.Mockito.when;
 
 public class TransportKibanaEnrollmentActionTests extends ESTestCase {
-    private List<ChangePasswordRequest> changePasswordRequests;
+    private List<CreateServiceAccountTokenRequest> createServiceAccountTokenRequests;
     private TransportKibanaEnrollmentAction action;
     private Client client;
+    private static final String TOKEN_NAME = TransportKibanaEnrollmentAction.getTokenName();
+    private static final SecureString TOKEN_VALUE = new SecureString("token-value".toCharArray());
 
     @BeforeClass
     public static void muteInFips(){
@@ -58,7 +60,7 @@ public static void muteInFips(){
     }
 
     @Before @SuppressWarnings("unchecked") public void setup() throws Exception {
-        changePasswordRequests = new ArrayList<>();
+        createServiceAccountTokenRequests = new ArrayList<>();
         final Environment env = mock(Environment.class);
         final Path tempDir = createTempDir();
         final Path httpCaPath = tempDir.resolve("httpCa.p12");
@@ -80,12 +82,13 @@ public static void muteInFips(){
         client = mock(Client.class);
         when(client.threadPool()).thenReturn(threadPool);
         doAnswer(invocation -> {
-            ChangePasswordRequest changePasswordRequest = (ChangePasswordRequest) invocation.getArguments()[1];
-            changePasswordRequests.add(changePasswordRequest);
-            ActionListener<ActionResponse.Empty> listener = (ActionListener) invocation.getArguments()[2];
-            listener.onResponse(ActionResponse.Empty.INSTANCE);
+            CreateServiceAccountTokenRequest createServiceAccountTokenRequest =
+                (CreateServiceAccountTokenRequest) invocation.getArguments()[1];
+            createServiceAccountTokenRequests.add(createServiceAccountTokenRequest);
+            ActionListener<CreateServiceAccountTokenResponse> listener = (ActionListener) invocation.getArguments()[2];
+            listener.onResponse(CreateServiceAccountTokenResponse.created(TOKEN_NAME, TOKEN_VALUE));
             return null;
-        }).when(client).execute(eq(ChangePasswordAction.INSTANCE), any(), any());
+        }).when(client).execute(eq(CreateServiceAccountTokenAction.INSTANCE), any(), any());
 
         final TransportService transportService = new TransportService(Settings.EMPTY,
             mock(Transport.class),
@@ -98,6 +101,7 @@ public static void muteInFips(){
     }
 
     public void testKibanaEnrollment() {
+        assertThat(TOKEN_NAME, startsWith("enroll-process-token-"));
         final KibanaEnrollmentRequest request = new KibanaEnrollmentRequest();
         final PlainActionFuture<KibanaEnrollmentResponse> future = new PlainActionFuture<>();
         action.doExecute(mock(Task.class), request, future);
@@ -105,22 +109,22 @@ public void testKibanaEnrollment() {
         assertThat(response.getHttpCa(), startsWith("MIIDSjCCAjKgAwIBAgIVALCgZXvbceUrjJaQMheDCX0kXnRJMA0GCSqGSIb3DQEBCwUAMDQxMjAw" +
             "BgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2VuZXJhdGVkIENBMB4XDTIxMDQyODEyNTY0MVoXDTI0MDQyNzEyNTY0MVowNDEyMDAGA1UEA" +
             "xMpRWxhc3RpYyBDZXJ0aWZpY2F0ZSBUb29sIEF1dG9nZW5lcmF0ZWQgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCCJbOU4JvxDD/F"));
-        assertNotNull(response.getPassword());
-        assertThat(changePasswordRequests.size(), equalTo(1));
+        assertThat(response.getTokenValue(), equalTo(TOKEN_VALUE));
+        assertThat(createServiceAccountTokenRequests.size(), equalTo(1));
     }
 
-    public void testKibanaEnrollmentFailedPasswordChange() {
+    public void testKibanaEnrollmentFailedTokenCreation() {
         // Override change password mock
         doAnswer(invocation -> {
             @SuppressWarnings("unchecked")
-            ActionListener<ActionResponse.Empty> listener = (ActionListener<ActionResponse.Empty>) invocation.getArguments()[2];
-            listener.onFailure(new ValidationException());
+            ActionListener<CreateServiceAccountTokenResponse> listener = (ActionListener) invocation.getArguments()[2];
+            listener.onFailure(new IllegalStateException());
             return null;
-        }).when(client).execute(eq(ChangePasswordAction.INSTANCE), any(), any());
+        }).when(client).execute(eq(CreateServiceAccountTokenAction.INSTANCE), any(), any());
         final KibanaEnrollmentRequest request = new KibanaEnrollmentRequest();
         final PlainActionFuture<KibanaEnrollmentResponse> future = new PlainActionFuture<>();
         action.doExecute(mock(Task.class), request, future);
         ElasticsearchException e = expectThrows(ElasticsearchException.class, future::actionGet);
-        assertThat(e.getDetailedMessage(), containsString("Failed to set the password for user [kibana_system]"));
+        assertThat(e.getDetailedMessage(), containsString("Failed to create token for the [elastic/kibana] service account"));
     }
 }