diff --git a/buildSrc/version.properties b/buildSrc/version.properties
index c98e265792b..6009021da14 100644
--- a/buildSrc/version.properties
+++ b/buildSrc/version.properties
@@ -1,5 +1,5 @@
elasticsearch = 7.0.0-alpha1
-lucene = 7.4.0-snapshot-cc2ee23050
+lucene = 7.4.0-snapshot-1cbadda4d3
# optional dependencies
spatial4j = 0.7
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java
index 0f9e9e58226..846f29bfb6e 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java
@@ -21,8 +21,6 @@ package org.elasticsearch.client;
import org.apache.http.Header;
import org.elasticsearch.action.ActionListener;
-import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
-import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
import org.elasticsearch.action.ingest.PutPipelineRequest;
@@ -68,28 +66,6 @@ public final class ClusterClient {
ClusterUpdateSettingsResponse::fromXContent, listener, emptySet(), headers);
}
- /**
- * Get current tasks using the Task Management API
- *
- * See
- * Task Management API on elastic.co
- */
- public ListTasksResponse listTasks(ListTasksRequest request, Header... headers) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::listTasks, ListTasksResponse::fromXContent,
- emptySet(), headers);
- }
-
- /**
- * Asynchronously get current tasks using the Task Management API
- *
- * See
- * Task Management API on elastic.co
- */
- public void listTasksAsync(ListTasksRequest request, ActionListener listener, Header... headers) {
- restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::listTasks, ListTasksResponse::fromXContent,
- listener, emptySet(), headers);
- }
-
/**
* Add a pipeline or update an existing pipeline in the cluster
*
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
index 68e32abb69d..8537bf3b450 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
@@ -192,6 +192,7 @@ public class RestHighLevelClient implements Closeable {
private final IndicesClient indicesClient = new IndicesClient(this);
private final ClusterClient clusterClient = new ClusterClient(this);
private final SnapshotClient snapshotClient = new SnapshotClient(this);
+ private final TasksClient tasksClient = new TasksClient(this);
/**
* Creates a {@link RestHighLevelClient} given the low level {@link RestClientBuilder} that allows to build the
@@ -264,6 +265,15 @@ public class RestHighLevelClient implements Closeable {
return snapshotClient;
}
+ /**
+ * Provides a {@link TasksClient} which can be used to access the Tasks API.
+ *
+ * See Task Management API on elastic.co
+ */
+ public final TasksClient tasks() {
+ return tasksClient;
+ }
+
/**
* Executes a bulk request using the Bulk API
*
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksClient.java
new file mode 100644
index 00000000000..214f1e7884a
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksClient.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.apache.http.Header;
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
+import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
+
+import java.io.IOException;
+
+import static java.util.Collections.emptySet;
+
+/**
+ * A wrapper for the {@link RestHighLevelClient} that provides methods for accessing the Tasks API.
+ *
+ * See Task Management API on elastic.co
+ */
+public class TasksClient {
+ private final RestHighLevelClient restHighLevelClient;
+
+ TasksClient(RestHighLevelClient restHighLevelClient) {
+ this.restHighLevelClient = restHighLevelClient;
+ }
+
+ /**
+ * Get current tasks using the Task Management API
+ *
+ * See
+ * Task Management API on elastic.co
+ */
+ public ListTasksResponse list(ListTasksRequest request, Header... headers) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::listTasks, ListTasksResponse::fromXContent,
+ emptySet(), headers);
+ }
+
+ /**
+ * Asynchronously get current tasks using the Task Management API
+ *
+ * See
+ * Task Management API on elastic.co
+ */
+ public void listAsync(ListTasksRequest request, ActionListener listener, Header... headers) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::listTasks, ListTasksResponse::fromXContent,
+ listener, emptySet(), headers);
+ }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java
index d41117ceb6d..44332b058bc 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java
@@ -20,9 +20,6 @@
package org.elasticsearch.client;
import org.elasticsearch.ElasticsearchException;
-import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
-import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
-import org.elasticsearch.action.admin.cluster.node.tasks.list.TaskGroup;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
import org.elasticsearch.action.ingest.PutPipelineRequest;
@@ -37,16 +34,13 @@ import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.indices.recovery.RecoverySettings;
import org.elasticsearch.ingest.Pipeline;
import org.elasticsearch.rest.RestStatus;
-import org.elasticsearch.tasks.TaskInfo;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
-import static java.util.Collections.emptyList;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
@@ -117,31 +111,6 @@ public class ClusterClientIT extends ESRestHighLevelClientTestCase {
"Elasticsearch exception [type=illegal_argument_exception, reason=transient setting [" + setting + "], not recognized]"));
}
- public void testListTasks() throws IOException {
- ListTasksRequest request = new ListTasksRequest();
- ListTasksResponse response = execute(request, highLevelClient().cluster()::listTasks, highLevelClient().cluster()::listTasksAsync);
-
- assertThat(response, notNullValue());
- assertThat(response.getNodeFailures(), equalTo(emptyList()));
- assertThat(response.getTaskFailures(), equalTo(emptyList()));
- // It's possible that there are other tasks except 'cluster:monitor/tasks/lists[n]' and 'action":"cluster:monitor/tasks/lists'
- assertThat(response.getTasks().size(), greaterThanOrEqualTo(2));
- boolean listTasksFound = false;
- for (TaskGroup taskGroup : response.getTaskGroups()) {
- TaskInfo parent = taskGroup.getTaskInfo();
- if ("cluster:monitor/tasks/lists".equals(parent.getAction())) {
- assertThat(taskGroup.getChildTasks().size(), equalTo(1));
- TaskGroup childGroup = taskGroup.getChildTasks().iterator().next();
- assertThat(childGroup.getChildTasks().isEmpty(), equalTo(true));
- TaskInfo child = childGroup.getTaskInfo();
- assertThat(child.getAction(), equalTo("cluster:monitor/tasks/lists[n]"));
- assertThat(child.getParentTaskId(), equalTo(parent.getTaskId()));
- listTasksFound = true;
- }
- }
- assertTrue("List tasks were not found", listTasksFound);
- }
-
public void testPutPipeline() throws IOException {
String id = "some_pipeline_id";
XContentType xContentType = randomFrom(XContentType.values());
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/TasksIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/TasksIT.java
new file mode 100644
index 00000000000..fc7d70a36e1
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/TasksIT.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
+import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
+import org.elasticsearch.action.admin.cluster.node.tasks.list.TaskGroup;
+import org.elasticsearch.tasks.TaskInfo;
+
+import java.io.IOException;
+
+import static java.util.Collections.emptyList;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.notNullValue;
+
+public class TasksIT extends ESRestHighLevelClientTestCase {
+
+ public void testListTasks() throws IOException {
+ ListTasksRequest request = new ListTasksRequest();
+ ListTasksResponse response = execute(request, highLevelClient().tasks()::list, highLevelClient().tasks()::listAsync);
+
+ assertThat(response, notNullValue());
+ assertThat(response.getNodeFailures(), equalTo(emptyList()));
+ assertThat(response.getTaskFailures(), equalTo(emptyList()));
+ // It's possible that there are other tasks except 'cluster:monitor/tasks/lists[n]' and 'action":"cluster:monitor/tasks/lists'
+ assertThat(response.getTasks().size(), greaterThanOrEqualTo(2));
+ boolean listTasksFound = false;
+ for (TaskGroup taskGroup : response.getTaskGroups()) {
+ TaskInfo parent = taskGroup.getTaskInfo();
+ if ("cluster:monitor/tasks/lists".equals(parent.getAction())) {
+ assertThat(taskGroup.getChildTasks().size(), equalTo(1));
+ TaskGroup childGroup = taskGroup.getChildTasks().iterator().next();
+ assertThat(childGroup.getChildTasks().isEmpty(), equalTo(true));
+ TaskInfo child = childGroup.getTaskInfo();
+ assertThat(child.getAction(), equalTo("cluster:monitor/tasks/lists[n]"));
+ assertThat(child.getParentTaskId(), equalTo(parent.getTaskId()));
+ listTasksFound = true;
+ }
+ }
+ assertTrue("List tasks were not found", listTasksFound);
+ }
+
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java
index b9329f99a3c..29bb2d05afc 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java
@@ -19,13 +19,8 @@
package org.elasticsearch.client.documentation;
-import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.LatchedActionListener;
-import org.elasticsearch.action.TaskOperationFailure;
-import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
-import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
-import org.elasticsearch.action.admin.cluster.node.tasks.list.TaskGroup;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
import org.elasticsearch.action.ingest.PutPipelineRequest;
@@ -39,21 +34,15 @@ import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.indices.recovery.RecoverySettings;
-import org.elasticsearch.tasks.TaskId;
-import org.elasticsearch.tasks.TaskInfo;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import static java.util.Collections.emptyList;
import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.greaterThanOrEqualTo;
-import static org.hamcrest.Matchers.notNullValue;
/**
* This class is used to generate the Java Cluster API documentation.
@@ -193,89 +182,6 @@ public class ClusterClientDocumentationIT extends ESRestHighLevelClientTestCase
}
}
- public void testListTasks() throws IOException {
- RestHighLevelClient client = highLevelClient();
- {
- // tag::list-tasks-request
- ListTasksRequest request = new ListTasksRequest();
- // end::list-tasks-request
-
- // tag::list-tasks-request-filter
- request.setActions("cluster:*"); // <1>
- request.setNodes("nodeId1", "nodeId2"); // <2>
- request.setParentTaskId(new TaskId("parentTaskId", 42)); // <3>
- // end::list-tasks-request-filter
-
- // tag::list-tasks-request-detailed
- request.setDetailed(true); // <1>
- // end::list-tasks-request-detailed
-
- // tag::list-tasks-request-wait-completion
- request.setWaitForCompletion(true); // <1>
- request.setTimeout(TimeValue.timeValueSeconds(50)); // <2>
- request.setTimeout("50s"); // <3>
- // end::list-tasks-request-wait-completion
- }
-
- ListTasksRequest request = new ListTasksRequest();
-
- // tag::list-tasks-execute
- ListTasksResponse response = client.cluster().listTasks(request);
- // end::list-tasks-execute
-
- assertThat(response, notNullValue());
-
- // tag::list-tasks-response-tasks
- List tasks = response.getTasks(); // <1>
- // end::list-tasks-response-tasks
-
- // tag::list-tasks-response-calc
- Map> perNodeTasks = response.getPerNodeTasks(); // <1>
- List groups = response.getTaskGroups(); // <2>
- // end::list-tasks-response-calc
-
- // tag::list-tasks-response-failures
- List nodeFailures = response.getNodeFailures(); // <1>
- List taskFailures = response.getTaskFailures(); // <2>
- // end::list-tasks-response-failures
-
- assertThat(response.getNodeFailures(), equalTo(emptyList()));
- assertThat(response.getTaskFailures(), equalTo(emptyList()));
- assertThat(response.getTasks().size(), greaterThanOrEqualTo(2));
- }
-
- public void testListTasksAsync() throws Exception {
- RestHighLevelClient client = highLevelClient();
- {
- ListTasksRequest request = new ListTasksRequest();
-
- // tag::list-tasks-execute-listener
- ActionListener listener =
- new ActionListener() {
- @Override
- public void onResponse(ListTasksResponse response) {
- // <1>
- }
-
- @Override
- public void onFailure(Exception e) {
- // <2>
- }
- };
- // end::list-tasks-execute-listener
-
- // Replace the empty listener by a blocking listener in test
- final CountDownLatch latch = new CountDownLatch(1);
- listener = new LatchedActionListener<>(listener, latch);
-
- // tag::list-tasks-execute-async
- client.cluster().listTasksAsync(request, listener); // <1>
- // end::list-tasks-execute-async
-
- assertTrue(latch.await(30L, TimeUnit.SECONDS));
- }
- }
-
public void testPutPipeline() throws IOException {
RestHighLevelClient client = highLevelClient();
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
index 0a57fafe5be..dc749a96bb8 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
@@ -45,7 +45,7 @@ import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.equalTo;
/**
- * This class is used to generate the Java Cluster API documentation.
+ * This class is used to generate the Java Snapshot API documentation.
* You need to wrap your code between two tags like:
* // tag::example
* // end::example
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/TasksClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/TasksClientDocumentationIT.java
new file mode 100644
index 00000000000..faf447a4143
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/TasksClientDocumentationIT.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client.documentation;
+
+import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.LatchedActionListener;
+import org.elasticsearch.action.TaskOperationFailure;
+import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
+import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
+import org.elasticsearch.action.admin.cluster.node.tasks.list.TaskGroup;
+import org.elasticsearch.client.ESRestHighLevelClientTestCase;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.tasks.TaskId;
+import org.elasticsearch.tasks.TaskInfo;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static java.util.Collections.emptyList;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.notNullValue;
+
+/**
+ * This class is used to generate the Java Tasks API documentation.
+ * You need to wrap your code between two tags like:
+ * // tag::example
+ * // end::example
+ *
+ * Where example is your tag name.
+ *
+ * Then in the documentation, you can extract what is between tag and end tags with
+ * ["source","java",subs="attributes,callouts,macros"]
+ * --------------------------------------------------
+ * include-tagged::{doc-tests}/{@link TasksClientDocumentationIT}.java[example]
+ * --------------------------------------------------
+ *
+ * The column width of the code block is 84. If the code contains a line longer
+ * than 84, the line will be cut and a horizontal scroll bar will be displayed.
+ * (the code indentation of the tag is not included in the width)
+ */
+public class TasksClientDocumentationIT extends ESRestHighLevelClientTestCase {
+
+ public void testListTasks() throws IOException {
+ RestHighLevelClient client = highLevelClient();
+ {
+ // tag::list-tasks-request
+ ListTasksRequest request = new ListTasksRequest();
+ // end::list-tasks-request
+
+ // tag::list-tasks-request-filter
+ request.setActions("cluster:*"); // <1>
+ request.setNodes("nodeId1", "nodeId2"); // <2>
+ request.setParentTaskId(new TaskId("parentTaskId", 42)); // <3>
+ // end::list-tasks-request-filter
+
+ // tag::list-tasks-request-detailed
+ request.setDetailed(true); // <1>
+ // end::list-tasks-request-detailed
+
+ // tag::list-tasks-request-wait-completion
+ request.setWaitForCompletion(true); // <1>
+ request.setTimeout(TimeValue.timeValueSeconds(50)); // <2>
+ request.setTimeout("50s"); // <3>
+ // end::list-tasks-request-wait-completion
+ }
+
+ ListTasksRequest request = new ListTasksRequest();
+
+ // tag::list-tasks-execute
+ ListTasksResponse response = client.tasks().list(request);
+ // end::list-tasks-execute
+
+ assertThat(response, notNullValue());
+
+ // tag::list-tasks-response-tasks
+ List tasks = response.getTasks(); // <1>
+ // end::list-tasks-response-tasks
+
+ // tag::list-tasks-response-calc
+ Map> perNodeTasks = response.getPerNodeTasks(); // <1>
+ List groups = response.getTaskGroups(); // <2>
+ // end::list-tasks-response-calc
+
+ // tag::list-tasks-response-failures
+ List nodeFailures = response.getNodeFailures(); // <1>
+ List taskFailures = response.getTaskFailures(); // <2>
+ // end::list-tasks-response-failures
+
+ assertThat(response.getNodeFailures(), equalTo(emptyList()));
+ assertThat(response.getTaskFailures(), equalTo(emptyList()));
+ assertThat(response.getTasks().size(), greaterThanOrEqualTo(2));
+ }
+
+ public void testListTasksAsync() throws Exception {
+ RestHighLevelClient client = highLevelClient();
+ {
+ ListTasksRequest request = new ListTasksRequest();
+
+ // tag::list-tasks-execute-listener
+ ActionListener listener =
+ new ActionListener() {
+ @Override
+ public void onResponse(ListTasksResponse response) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ // end::list-tasks-execute-listener
+
+ // Replace the empty listener by a blocking listener in test
+ final CountDownLatch latch = new CountDownLatch(1);
+ listener = new LatchedActionListener<>(listener, latch);
+
+ // tag::list-tasks-execute-async
+ client.tasks().listAsync(request, listener); // <1>
+ // end::list-tasks-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
+ }
+}
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index b04cbb8df79..981c2caa543 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -104,11 +104,9 @@ include::indices/put_template.asciidoc[]
The Java High Level REST Client supports the following Cluster APIs:
* <>
-* <>
* <>
include::cluster/put_settings.asciidoc[]
-include::cluster/list_tasks.asciidoc[]
include::cluster/put_pipeline.asciidoc[]
== Snapshot APIs
@@ -122,3 +120,11 @@ The Java High Level REST Client supports the following Snapshot APIs:
include::snapshot/get_repository.asciidoc[]
include::snapshot/create_repository.asciidoc[]
include::snapshot/delete_repository.asciidoc[]
+
+== Tasks APIs
+
+The Java High Level REST Client supports the following Tasks APIs:
+
+* <>
+
+include::tasks/list_tasks.asciidoc[]
diff --git a/docs/java-rest/high-level/cluster/list_tasks.asciidoc b/docs/java-rest/high-level/tasks/list_tasks.asciidoc
similarity index 79%
rename from docs/java-rest/high-level/cluster/list_tasks.asciidoc
rename to docs/java-rest/high-level/tasks/list_tasks.asciidoc
index 1a2117b2e66..e60ca61247e 100644
--- a/docs/java-rest/high-level/cluster/list_tasks.asciidoc
+++ b/docs/java-rest/high-level/tasks/list_tasks.asciidoc
@@ -1,4 +1,4 @@
-[[java-rest-high-cluster-list-tasks]]
+[[java-rest-high-tasks-list]]
=== List Tasks API
The List Tasks API allows to get information about the tasks currently executing in the cluster.
@@ -10,7 +10,7 @@ A `ListTasksRequest`:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-request]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-request]
--------------------------------------------------
There is no required parameters. By default the client will list all tasks and will not wait
for task completion.
@@ -19,7 +19,7 @@ for task completion.
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-request-filter]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-request-filter]
--------------------------------------------------
<1> Request only cluster-related tasks
<2> Request all tasks running on nodes nodeId1 and nodeId2
@@ -27,13 +27,13 @@ include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-request
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-request-detailed]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-request-detailed]
--------------------------------------------------
<1> Should the information include detailed, potentially slow to generate data. Defaults to `false`
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-request-wait-completion]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-request-wait-completion]
--------------------------------------------------
<1> Should this request wait for all found tasks to complete. Defaults to `false`
<2> Timeout for the request as a `TimeValue`. Applicable only if `setWaitForCompletion` is `true`.
@@ -45,7 +45,7 @@ Defaults to 30 seconds
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-execute]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-execute]
--------------------------------------------------
[[java-rest-high-cluster-list-tasks-async]]
@@ -57,7 +57,7 @@ passed to the asynchronous method:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-execute-async]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-execute-async]
--------------------------------------------------
<1> The `ListTasksRequest` to execute and the `ActionListener` to use
when the execution completes
@@ -71,7 +71,7 @@ A typical listener for `ListTasksResponse` looks like:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-execute-listener]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-execute-listener]
--------------------------------------------------
<1> Called when the execution is successfully completed. The response is
provided as an argument
@@ -82,20 +82,20 @@ provided as an argument
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-response-tasks]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-response-tasks]
--------------------------------------------------
<1> List of currently running tasks
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-response-calc]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-response-calc]
--------------------------------------------------
<1> List of tasks grouped by a node
<2> List of tasks grouped by a parent task
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
-include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[list-tasks-response-failures]
+include-tagged::{doc-tests}/TasksClientDocumentationIT.java[list-tasks-response-failures]
--------------------------------------------------
<1> List of node failures
<2> List of tasks failures
diff --git a/docs/reference/index.asciidoc b/docs/reference/index.asciidoc
index 59f8d77a0c0..8567ed63b34 100644
--- a/docs/reference/index.asciidoc
+++ b/docs/reference/index.asciidoc
@@ -26,6 +26,7 @@ include::{xes-repo-dir}/settings/configuring-xes.asciidoc[]
include::{xes-repo-dir}/setup/bootstrap-checks-xes.asciidoc[]
+:edit_url:
include::upgrade.asciidoc[]
include::migration/index.asciidoc[]
@@ -66,6 +67,7 @@ include::{xes-repo-dir}/rest-api/index.asciidoc[]
include::{xes-repo-dir}/commands/index.asciidoc[]
+:edit_url:
include::how-to.asciidoc[]
include::testing.asciidoc[]
diff --git a/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/CommonAnalysisPlugin.java b/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/CommonAnalysisPlugin.java
index 02a4197fba9..69c8afb3e2f 100644
--- a/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/CommonAnalysisPlugin.java
+++ b/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/CommonAnalysisPlugin.java
@@ -193,6 +193,7 @@ public class CommonAnalysisPlugin extends Plugin implements AnalysisPlugin {
tokenizers.put("pattern", PatternTokenizerFactory::new);
tokenizers.put("uax_url_email", UAX29URLEmailTokenizerFactory::new);
tokenizers.put("whitespace", WhitespaceTokenizerFactory::new);
+ tokenizers.put("keyword", KeywordTokenizerFactory::new);
return tokenizers;
}
diff --git a/server/src/main/java/org/elasticsearch/index/analysis/KeywordTokenizerFactory.java b/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/KeywordTokenizerFactory.java
similarity index 89%
rename from server/src/main/java/org/elasticsearch/index/analysis/KeywordTokenizerFactory.java
rename to modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/KeywordTokenizerFactory.java
index 1d94cad1507..abe88462cb9 100644
--- a/server/src/main/java/org/elasticsearch/index/analysis/KeywordTokenizerFactory.java
+++ b/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/KeywordTokenizerFactory.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.elasticsearch.index.analysis;
+package org.elasticsearch.analysis.common;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.core.KeywordTokenizer;
@@ -30,7 +30,7 @@ public class KeywordTokenizerFactory extends AbstractTokenizerFactory {
private final int bufferSize;
- public KeywordTokenizerFactory(IndexSettings indexSettings, Environment environment, String name, Settings settings) {
+ KeywordTokenizerFactory(IndexSettings indexSettings, Environment environment, String name, Settings settings) {
super(indexSettings, name, settings);
bufferSize = settings.getAsInt("buffer_size", 256);
}
diff --git a/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/CommonAnalysisFactoryTests.java b/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/CommonAnalysisFactoryTests.java
index 7deadcbcc25..50843065878 100644
--- a/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/CommonAnalysisFactoryTests.java
+++ b/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/CommonAnalysisFactoryTests.java
@@ -24,7 +24,6 @@ import org.apache.lucene.analysis.en.PorterStemFilterFactory;
import org.apache.lucene.analysis.miscellaneous.LimitTokenCountFilterFactory;
import org.apache.lucene.analysis.reverse.ReverseStringFilterFactory;
import org.apache.lucene.analysis.snowball.SnowballPorterFilterFactory;
-import org.elasticsearch.index.analysis.KeywordTokenizerFactory;
import org.elasticsearch.index.analysis.SoraniNormalizationFilterFactory;
import org.elasticsearch.index.analysis.SynonymTokenFilterFactory;
import org.elasticsearch.indices.analysis.AnalysisFactoryTestCase;
@@ -56,6 +55,7 @@ public class CommonAnalysisFactoryTests extends AnalysisFactoryTestCase {
tokenizers.put("pattern", PatternTokenizerFactory.class);
tokenizers.put("uax29urlemail", UAX29URLEmailTokenizerFactory.class);
tokenizers.put("whitespace", WhitespaceTokenizerFactory.class);
+ tokenizers.put("keyword", KeywordTokenizerFactory.class);
return tokenizers;
}
diff --git a/modules/analysis-common/src/test/resources/rest-api-spec/test/analysis-common/30_tokenizers.yml b/modules/analysis-common/src/test/resources/rest-api-spec/test/analysis-common/30_tokenizers.yml
index cffd4496f1f..9a7c158fc47 100644
--- a/modules/analysis-common/src/test/resources/rest-api-spec/test/analysis-common/30_tokenizers.yml
+++ b/modules/analysis-common/src/test/resources/rest-api-spec/test/analysis-common/30_tokenizers.yml
@@ -5,9 +5,22 @@
indices.analyze:
body:
text: Foo Bar!
+ explain: true
tokenizer: keyword
- - length: { tokens: 1 }
- - match: { tokens.0.token: Foo Bar! }
+ - length: { detail.tokenizer.tokens: 1 }
+ - match: { detail.tokenizer.name: keyword }
+ - match: { detail.tokenizer.tokens.0.token: Foo Bar! }
+
+ - do:
+ indices.analyze:
+ body:
+ text: Foo Bar!
+ explain: true
+ tokenizer:
+ type: keyword
+ - length: { detail.tokenizer.tokens: 1 }
+ - match: { detail.tokenizer.name: _anonymous_tokenizer }
+ - match: { detail.tokenizer.tokens.0.token: Foo Bar! }
---
"nGram":
diff --git a/modules/analysis-common/src/test/resources/rest-api-spec/test/indices.analyze/10_analyze.yml b/modules/analysis-common/src/test/resources/rest-api-spec/test/indices.analyze/10_analyze.yml
index 1737d743a6d..936736e93de 100644
--- a/modules/analysis-common/src/test/resources/rest-api-spec/test/indices.analyze/10_analyze.yml
+++ b/modules/analysis-common/src/test/resources/rest-api-spec/test/indices.analyze/10_analyze.yml
@@ -97,3 +97,19 @@
- length: { tokens: 2 }
- match: { tokens.0.token: sha }
- match: { tokens.1.token: hay }
+
+---
+"Custom normalizer in request":
+ - do:
+ indices.analyze:
+ body:
+ text: ABc
+ explain: true
+ filter: ["lowercase"]
+
+ - length: { detail.tokenizer.tokens: 1 }
+ - length: { detail.tokenfilters.0.tokens: 1 }
+ - match: { detail.tokenizer.name: keyword_for_normalizer }
+ - match: { detail.tokenizer.tokens.0.token: ABc }
+ - match: { detail.tokenfilters.0.name: lowercase }
+ - match: { detail.tokenfilters.0.tokens.0.token: abc }
diff --git a/modules/lang-expression/licenses/lucene-expressions-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/modules/lang-expression/licenses/lucene-expressions-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..3bbaa2ba0a7
--- /dev/null
+++ b/modules/lang-expression/licenses/lucene-expressions-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+98c920972b2f5e8563540e805d87e6a3bc888972
\ No newline at end of file
diff --git a/modules/lang-expression/licenses/lucene-expressions-7.4.0-snapshot-cc2ee23050.jar.sha1 b/modules/lang-expression/licenses/lucene-expressions-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 8222106897b..00000000000
--- a/modules/lang-expression/licenses/lucene-expressions-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1e28b448387ec05d655f8c81ee54e13ff2975a4d
\ No newline at end of file
diff --git a/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateIT.java b/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateIT.java
index fe2fedf62b5..884e26e7df8 100644
--- a/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateIT.java
+++ b/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateIT.java
@@ -198,6 +198,7 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
getResponse = client().admin().cluster().prepareGetStoredScript("testTemplate").get();
assertNull(getResponse.getSource());
+ assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
public void testIndexedTemplate() throws Exception {
@@ -267,6 +268,7 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
.setScript("2").setScriptType(ScriptType.STORED).setScriptParams(templateParams)
.get();
assertHitCount(searchResponse.getResponse(), 1);
+ assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
// Relates to #10397
@@ -311,6 +313,7 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
.get();
assertHitCount(searchResponse.getResponse(), 1);
}
+ assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
public void testIndexedTemplateWithArray() throws Exception {
@@ -339,6 +342,7 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
.setScript("4").setScriptType(ScriptType.STORED).setScriptParams(arrayTemplateParams)
.get();
assertHitCount(searchResponse.getResponse(), 5);
+ assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
}
diff --git a/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpServerTransport.java b/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpServerTransport.java
index 45e889797bd..31c1214f034 100644
--- a/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpServerTransport.java
+++ b/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpServerTransport.java
@@ -56,6 +56,7 @@ import org.elasticsearch.common.util.concurrent.EsExecutors;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.http.AbstractHttpServerTransport;
import org.elasticsearch.http.BindHttpException;
import org.elasticsearch.http.HttpHandlingSettings;
import org.elasticsearch.http.HttpStats;
diff --git a/modules/transport-netty4/src/test/java/org/elasticsearch/http/netty4/Netty4HttpServerTransportTests.java b/modules/transport-netty4/src/test/java/org/elasticsearch/http/netty4/Netty4HttpServerTransportTests.java
index 96b436ce7de..5b22409b92d 100644
--- a/modules/transport-netty4/src/test/java/org/elasticsearch/http/netty4/Netty4HttpServerTransportTests.java
+++ b/modules/transport-netty4/src/test/java/org/elasticsearch/http/netty4/Netty4HttpServerTransportTests.java
@@ -273,7 +273,7 @@ public class Netty4HttpServerTransportTests extends ESTestCase {
try (Netty4HttpServerTransport transport =
new Netty4HttpServerTransport(settings, networkService, bigArrays, threadPool, xContentRegistry(), dispatcher)) {
transport.start();
- final TransportAddress remoteAddress = randomFrom(transport.boundAddress.boundAddresses());
+ final TransportAddress remoteAddress = randomFrom(transport.boundAddress().boundAddresses());
try (Netty4HttpClient client = new Netty4HttpClient()) {
final String url = "/" + new String(new byte[maxInitialLineLength], Charset.forName("UTF-8"));
@@ -352,7 +352,7 @@ public class Netty4HttpServerTransportTests extends ESTestCase {
try (Netty4HttpServerTransport transport =
new Netty4HttpServerTransport(settings, networkService, bigArrays, threadPool, xContentRegistry(), dispatcher)) {
transport.start();
- final TransportAddress remoteAddress = randomFrom(transport.boundAddress.boundAddresses());
+ final TransportAddress remoteAddress = randomFrom(transport.boundAddress().boundAddresses());
AtomicBoolean channelClosed = new AtomicBoolean(false);
diff --git a/plugins/analysis-icu/licenses/lucene-analyzers-icu-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/plugins/analysis-icu/licenses/lucene-analyzers-icu-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..7f3d3b5ccf6
--- /dev/null
+++ b/plugins/analysis-icu/licenses/lucene-analyzers-icu-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+844e2b76f4bc6e646e1c3257d668ac598e03f36a
\ No newline at end of file
diff --git a/plugins/analysis-icu/licenses/lucene-analyzers-icu-7.4.0-snapshot-cc2ee23050.jar.sha1 b/plugins/analysis-icu/licenses/lucene-analyzers-icu-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 781b814c99e..00000000000
--- a/plugins/analysis-icu/licenses/lucene-analyzers-icu-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-452c9a9f86b79b9b3eaa7d6aa782e189d5bcfe8f
\ No newline at end of file
diff --git a/plugins/analysis-icu/src/test/resources/rest-api-spec/test/analysis_icu/10_basic.yml b/plugins/analysis-icu/src/test/resources/rest-api-spec/test/analysis_icu/10_basic.yml
index 521d8f07140..c9ff2b2fb64 100644
--- a/plugins/analysis-icu/src/test/resources/rest-api-spec/test/analysis_icu/10_basic.yml
+++ b/plugins/analysis-icu/src/test/resources/rest-api-spec/test/analysis_icu/10_basic.yml
@@ -16,9 +16,11 @@
body:
filter: [icu_normalizer]
text: Foo Bar Ruß
- tokenizer: keyword
- - length: { tokens: 1 }
- - match: { tokens.0.token: foo bar russ }
+ tokenizer: standard
+ - length: { tokens: 3 }
+ - match: { tokens.0.token: foo}
+ - match: { tokens.1.token: bar }
+ - match: { tokens.2.token: russ }
---
"Normalization charfilter":
- do:
@@ -26,9 +28,11 @@
body:
char_filter: [icu_normalizer]
text: Foo Bar Ruß
- tokenizer: keyword
- - length: { tokens: 1 }
- - match: { tokens.0.token: foo bar russ }
+ tokenizer: standard
+ - length: { tokens: 3 }
+ - match: { tokens.0.token: foo }
+ - match: { tokens.1.token: bar }
+ - match: { tokens.2.token: russ }
---
"Folding filter":
- do:
@@ -36,9 +40,11 @@
body:
filter: [icu_folding]
text: Foo Bar résumé
- tokenizer: keyword
- - length: { tokens: 1 }
- - match: { tokens.0.token: foo bar resume }
+ tokenizer: standard
+ - length: { tokens: 3 }
+ - match: { tokens.0.token: foo }
+ - match: { tokens.1.token: bar }
+ - match: { tokens.2.token: resume }
---
"Normalization with a UnicodeSet Filter":
- do:
@@ -64,25 +70,34 @@
index: test
body:
char_filter: ["charfilter_icu_normalizer"]
- tokenizer: keyword
+ tokenizer: standard
text: charfilter Föo Bâr Ruß
- - length: { tokens: 1 }
- - match: { tokens.0.token: charfilter föo bâr ruß }
+ - length: { tokens: 4 }
+ - match: { tokens.0.token: charfilter }
+ - match: { tokens.1.token: föo }
+ - match: { tokens.2.token: bâr }
+ - match: { tokens.3.token: ruß }
- do:
indices.analyze:
index: test
body:
- tokenizer: keyword
+ tokenizer: standard
filter: ["tokenfilter_icu_normalizer"]
text: tokenfilter Föo Bâr Ruß
- - length: { tokens: 1 }
- - match: { tokens.0.token: tokenfilter föo Bâr ruß }
+ - length: { tokens: 4 }
+ - match: { tokens.0.token: tokenfilter }
+ - match: { tokens.1.token: föo }
+ - match: { tokens.2.token: Bâr }
+ - match: { tokens.3.token: ruß }
- do:
indices.analyze:
index: test
body:
- tokenizer: keyword
+ tokenizer: standard
filter: ["tokenfilter_icu_folding"]
text: icufolding Föo Bâr Ruß
- - length: { tokens: 1 }
- - match: { tokens.0.token: icufolding foo bâr russ }
+ - length: { tokens: 4 }
+ - match: { tokens.0.token: icufolding }
+ - match: { tokens.1.token: foo }
+ - match: { tokens.2.token: bâr }
+ - match: { tokens.3.token: russ }
diff --git a/plugins/analysis-kuromoji/licenses/lucene-analyzers-kuromoji-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/plugins/analysis-kuromoji/licenses/lucene-analyzers-kuromoji-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..65423fff2a4
--- /dev/null
+++ b/plugins/analysis-kuromoji/licenses/lucene-analyzers-kuromoji-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+2f2bd2d67c7952e4ae14ab3f742824a45d0d1719
\ No newline at end of file
diff --git a/plugins/analysis-kuromoji/licenses/lucene-analyzers-kuromoji-7.4.0-snapshot-cc2ee23050.jar.sha1 b/plugins/analysis-kuromoji/licenses/lucene-analyzers-kuromoji-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index baba0897858..00000000000
--- a/plugins/analysis-kuromoji/licenses/lucene-analyzers-kuromoji-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-48c76a922bdfc7f50b1b6fe22e9456c555f3f990
\ No newline at end of file
diff --git a/plugins/analysis-nori/licenses/lucene-analyzers-nori-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/plugins/analysis-nori/licenses/lucene-analyzers-nori-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..04fa62ce64a
--- /dev/null
+++ b/plugins/analysis-nori/licenses/lucene-analyzers-nori-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+46ad7ebcfcdbdb60dd54aae4d720356a7a51c7c0
\ No newline at end of file
diff --git a/plugins/analysis-nori/licenses/lucene-analyzers-nori-7.4.0-snapshot-cc2ee23050.jar.sha1 b/plugins/analysis-nori/licenses/lucene-analyzers-nori-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index da19e1c3857..00000000000
--- a/plugins/analysis-nori/licenses/lucene-analyzers-nori-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4db5777df468b0867ff6539c9ab687e0ed6cab41
\ No newline at end of file
diff --git a/plugins/analysis-phonetic/licenses/lucene-analyzers-phonetic-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/plugins/analysis-phonetic/licenses/lucene-analyzers-phonetic-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..55bc8869196
--- /dev/null
+++ b/plugins/analysis-phonetic/licenses/lucene-analyzers-phonetic-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+548e9f2b4d4a985dc174b2eee4007c0bd5642e68
\ No newline at end of file
diff --git a/plugins/analysis-phonetic/licenses/lucene-analyzers-phonetic-7.4.0-snapshot-cc2ee23050.jar.sha1 b/plugins/analysis-phonetic/licenses/lucene-analyzers-phonetic-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 148b5425d64..00000000000
--- a/plugins/analysis-phonetic/licenses/lucene-analyzers-phonetic-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0e09e6b011ab2b1a0e3e0e1df2ab2a91dca8ba23
\ No newline at end of file
diff --git a/plugins/analysis-smartcn/licenses/lucene-analyzers-smartcn-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/plugins/analysis-smartcn/licenses/lucene-analyzers-smartcn-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..be668543216
--- /dev/null
+++ b/plugins/analysis-smartcn/licenses/lucene-analyzers-smartcn-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+b90e66f4104f0234cfef335762f65a6fed695231
\ No newline at end of file
diff --git a/plugins/analysis-smartcn/licenses/lucene-analyzers-smartcn-7.4.0-snapshot-cc2ee23050.jar.sha1 b/plugins/analysis-smartcn/licenses/lucene-analyzers-smartcn-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index bce84d16a9a..00000000000
--- a/plugins/analysis-smartcn/licenses/lucene-analyzers-smartcn-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ceefa0f9789ab9ea5c8ab9f67ed7a601a3ae6aa9
\ No newline at end of file
diff --git a/plugins/analysis-stempel/licenses/lucene-analyzers-stempel-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/plugins/analysis-stempel/licenses/lucene-analyzers-stempel-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..b77acdc34f3
--- /dev/null
+++ b/plugins/analysis-stempel/licenses/lucene-analyzers-stempel-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+929a4eb52b11f6d3f0df9c8eba014f5ee2464c67
\ No newline at end of file
diff --git a/plugins/analysis-stempel/licenses/lucene-analyzers-stempel-7.4.0-snapshot-cc2ee23050.jar.sha1 b/plugins/analysis-stempel/licenses/lucene-analyzers-stempel-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 762c56f7700..00000000000
--- a/plugins/analysis-stempel/licenses/lucene-analyzers-stempel-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b013adc183e52a74795ad3d3032f4d0f9db30b73
\ No newline at end of file
diff --git a/plugins/analysis-stempel/src/test/resources/rest-api-spec/test/analysis_stempel/10_basic.yml b/plugins/analysis-stempel/src/test/resources/rest-api-spec/test/analysis_stempel/10_basic.yml
index 1941126c64f..3400a7f9bdf 100644
--- a/plugins/analysis-stempel/src/test/resources/rest-api-spec/test/analysis_stempel/10_basic.yml
+++ b/plugins/analysis-stempel/src/test/resources/rest-api-spec/test/analysis_stempel/10_basic.yml
@@ -5,7 +5,7 @@
indices.analyze:
body:
text: studenci
- tokenizer: keyword
+ tokenizer: standard
filter: [polish_stem]
- length: { tokens: 1 }
- match: { tokens.0.token: student }
diff --git a/plugins/analysis-ukrainian/licenses/lucene-analyzers-morfologik-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/plugins/analysis-ukrainian/licenses/lucene-analyzers-morfologik-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..cce4b6ff18d
--- /dev/null
+++ b/plugins/analysis-ukrainian/licenses/lucene-analyzers-morfologik-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+0e6575a411b65cd95e0e54f04d3da278b68be521
\ No newline at end of file
diff --git a/plugins/analysis-ukrainian/licenses/lucene-analyzers-morfologik-7.4.0-snapshot-cc2ee23050.jar.sha1 b/plugins/analysis-ukrainian/licenses/lucene-analyzers-morfologik-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 7631bea2569..00000000000
--- a/plugins/analysis-ukrainian/licenses/lucene-analyzers-morfologik-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-95300f29418f60e57e022d934d3462be9e1e2225
\ No newline at end of file
diff --git a/plugins/repository-azure/src/main/java/org/elasticsearch/repositories/azure/AzureStorageServiceImpl.java b/plugins/repository-azure/src/main/java/org/elasticsearch/repositories/azure/AzureStorageServiceImpl.java
index f21dbdfd269..6f4f8cfea96 100644
--- a/plugins/repository-azure/src/main/java/org/elasticsearch/repositories/azure/AzureStorageServiceImpl.java
+++ b/plugins/repository-azure/src/main/java/org/elasticsearch/repositories/azure/AzureStorageServiceImpl.java
@@ -35,6 +35,7 @@ import com.microsoft.azure.storage.blob.DeleteSnapshotsOption;
import com.microsoft.azure.storage.blob.ListBlobItem;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.util.Supplier;
+import org.elasticsearch.common.Strings;
import org.elasticsearch.common.blobstore.BlobMetaData;
import org.elasticsearch.common.blobstore.support.PlainBlobMetaData;
import org.elasticsearch.common.collect.MapBuilder;
@@ -45,6 +46,7 @@ import org.elasticsearch.repositories.RepositoryException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
@@ -52,66 +54,59 @@ import java.util.Map;
public class AzureStorageServiceImpl extends AbstractComponent implements AzureStorageService {
final Map storageSettings;
-
- final Map clients = new HashMap<>();
+ final Map clients;
public AzureStorageServiceImpl(Settings settings, Map storageSettings) {
super(settings);
-
- this.storageSettings = storageSettings;
-
if (storageSettings.isEmpty()) {
// If someone did not register any settings, they basically can't use the plugin
throw new IllegalArgumentException("If you want to use an azure repository, you need to define a client configuration.");
}
-
- logger.debug("starting azure storage client instance");
-
- // We register all regular azure clients
- for (Map.Entry azureStorageSettingsEntry : this.storageSettings.entrySet()) {
- logger.debug("registering regular client for account [{}]", azureStorageSettingsEntry.getKey());
- createClient(azureStorageSettingsEntry.getValue());
- }
+ this.storageSettings = storageSettings;
+ this.clients = createClients(storageSettings);
}
- void createClient(AzureStorageSettings azureStorageSettings) {
- try {
- logger.trace("creating new Azure storage client using account [{}], key [{}], endpoint suffix [{}]",
- azureStorageSettings.getAccount(), azureStorageSettings.getKey(), azureStorageSettings.getEndpointSuffix());
+ private Map createClients(final Map storageSettings) {
+ final Map clients = new HashMap<>();
+ for (Map.Entry azureStorageEntry : storageSettings.entrySet()) {
+ final String clientName = azureStorageEntry.getKey();
+ final AzureStorageSettings clientSettings = azureStorageEntry.getValue();
+ try {
+ logger.trace("creating new Azure storage client with name [{}]", clientName);
+ String storageConnectionString =
+ "DefaultEndpointsProtocol=https;"
+ + "AccountName=" + clientSettings.getAccount() + ";"
+ + "AccountKey=" + clientSettings.getKey();
- String storageConnectionString =
- "DefaultEndpointsProtocol=https;"
- + "AccountName=" + azureStorageSettings.getAccount() + ";"
- + "AccountKey=" + azureStorageSettings.getKey();
+ final String endpointSuffix = clientSettings.getEndpointSuffix();
+ if (Strings.hasLength(endpointSuffix)) {
+ storageConnectionString += ";EndpointSuffix=" + endpointSuffix;
+ }
+ // Retrieve storage account from connection-string.
+ CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString);
- String endpointSuffix = azureStorageSettings.getEndpointSuffix();
- if (endpointSuffix != null && !endpointSuffix.isEmpty()) {
- storageConnectionString += ";EndpointSuffix=" + endpointSuffix;
+ // Create the blob client.
+ CloudBlobClient client = storageAccount.createCloudBlobClient();
+
+ // Register the client
+ clients.put(clientSettings.getAccount(), client);
+ } catch (Exception e) {
+ logger.error(() -> new ParameterizedMessage("Can not create azure storage client [{}]", clientName), e);
}
- // Retrieve storage account from connection-string.
- CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString);
-
- // Create the blob client.
- CloudBlobClient client = storageAccount.createCloudBlobClient();
-
- // Register the client
- this.clients.put(azureStorageSettings.getAccount(), client);
- } catch (Exception e) {
- logger.error("can not create azure storage client: {}", e.getMessage());
}
+ return Collections.unmodifiableMap(clients);
}
CloudBlobClient getSelectedClient(String clientName, LocationMode mode) {
logger.trace("selecting a client named [{}], mode [{}]", clientName, mode.name());
AzureStorageSettings azureStorageSettings = this.storageSettings.get(clientName);
if (azureStorageSettings == null) {
- throw new IllegalArgumentException("Can not find named azure client [" + clientName + "]. Check your settings.");
+ throw new IllegalArgumentException("Unable to find client with name [" + clientName + "]");
}
CloudBlobClient client = this.clients.get(azureStorageSettings.getAccount());
-
if (client == null) {
- throw new IllegalArgumentException("Can not find an azure client named [" + azureStorageSettings.getAccount() + "]");
+ throw new IllegalArgumentException("No account defined for client with name [" + clientName + "]");
}
// NOTE: for now, just set the location mode in case it is different;
diff --git a/plugins/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AzureStorageServiceTests.java b/plugins/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AzureStorageServiceTests.java
index 72cd015f148..447826dbf83 100644
--- a/plugins/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AzureStorageServiceTests.java
+++ b/plugins/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AzureStorageServiceTests.java
@@ -23,7 +23,6 @@ import com.microsoft.azure.storage.LocationMode;
import com.microsoft.azure.storage.RetryExponentialRetry;
import com.microsoft.azure.storage.blob.CloudBlobClient;
import com.microsoft.azure.storage.core.Base64;
-
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsException;
@@ -36,6 +35,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
+import java.util.Collections;
import java.util.Map;
import static org.elasticsearch.repositories.azure.AzureStorageServiceImpl.blobNameFromUri;
@@ -49,31 +49,14 @@ import static org.hamcrest.Matchers.nullValue;
public class AzureStorageServiceTests extends ESTestCase {
- private MockSecureSettings buildSecureSettings() {
- MockSecureSettings secureSettings = new MockSecureSettings();
- secureSettings.setString("azure.client.azure1.account", "myaccount1");
- secureSettings.setString("azure.client.azure1.key", "mykey1");
- secureSettings.setString("azure.client.azure2.account", "myaccount2");
- secureSettings.setString("azure.client.azure2.key", "mykey2");
- secureSettings.setString("azure.client.azure3.account", "myaccount3");
- secureSettings.setString("azure.client.azure3.key", "mykey3");
- return secureSettings;
- }
- private Settings buildSettings() {
- Settings settings = Settings.builder()
- .setSecureSettings(buildSecureSettings())
- .build();
- return settings;
- }
-
public void testReadSecuredSettings() {
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("azure.client.azure1.account", "myaccount1");
- secureSettings.setString("azure.client.azure1.key", "mykey1");
+ secureSettings.setString("azure.client.azure1.key", encodeKey("mykey1"));
secureSettings.setString("azure.client.azure2.account", "myaccount2");
- secureSettings.setString("azure.client.azure2.key", "mykey2");
+ secureSettings.setString("azure.client.azure2.key", encodeKey("mykey2"));
secureSettings.setString("azure.client.azure3.account", "myaccount3");
- secureSettings.setString("azure.client.azure3.key", "mykey3");
+ secureSettings.setString("azure.client.azure3.key", encodeKey("mykey3"));
Settings settings = Settings.builder().setSecureSettings(secureSettings)
.put("azure.client.azure3.endpoint_suffix", "my_endpoint_suffix").build();
@@ -88,9 +71,9 @@ public class AzureStorageServiceTests extends ESTestCase {
public void testCreateClientWithEndpointSuffix() {
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("azure.client.azure1.account", "myaccount1");
- secureSettings.setString("azure.client.azure1.key", Base64.encode("mykey1".getBytes(StandardCharsets.UTF_8)));
+ secureSettings.setString("azure.client.azure1.key", encodeKey("mykey1"));
secureSettings.setString("azure.client.azure2.account", "myaccount2");
- secureSettings.setString("azure.client.azure2.key", Base64.encode("mykey2".getBytes(StandardCharsets.UTF_8)));
+ secureSettings.setString("azure.client.azure2.key", encodeKey("mykey2"));
Settings settings = Settings.builder().setSecureSettings(secureSettings)
.put("azure.client.azure1.endpoint_suffix", "my_endpoint_suffix").build();
AzureStorageServiceImpl azureStorageService = new AzureStorageServiceImpl(settings, AzureStorageSettings.load(settings));
@@ -103,7 +86,7 @@ public class AzureStorageServiceTests extends ESTestCase {
public void testGetSelectedClientWithNoPrimaryAndSecondary() {
try {
- new AzureStorageServiceMockForSettings(Settings.EMPTY);
+ new AzureStorageServiceImpl(Settings.EMPTY, Collections.emptyMap());
fail("we should have raised an IllegalArgumentException");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), is("If you want to use an azure repository, you need to define a client configuration."));
@@ -111,11 +94,11 @@ public class AzureStorageServiceTests extends ESTestCase {
}
public void testGetSelectedClientNonExisting() {
- AzureStorageServiceImpl azureStorageService = new AzureStorageServiceMockForSettings(buildSettings());
+ AzureStorageServiceImpl azureStorageService = createAzureService(buildSettings());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> {
azureStorageService.getSelectedClient("azure4", LocationMode.PRIMARY_ONLY);
});
- assertThat(e.getMessage(), is("Can not find named azure client [azure4]. Check your settings."));
+ assertThat(e.getMessage(), is("Unable to find client with name [azure4]"));
}
public void testGetSelectedClientDefaultTimeout() {
@@ -123,7 +106,7 @@ public class AzureStorageServiceTests extends ESTestCase {
.setSecureSettings(buildSecureSettings())
.put("azure.client.azure3.timeout", "30s")
.build();
- AzureStorageServiceImpl azureStorageService = new AzureStorageServiceMockForSettings(timeoutSettings);
+ AzureStorageServiceImpl azureStorageService = createAzureService(timeoutSettings);
CloudBlobClient client1 = azureStorageService.getSelectedClient("azure1", LocationMode.PRIMARY_ONLY);
assertThat(client1.getDefaultRequestOptions().getTimeoutIntervalInMs(), nullValue());
CloudBlobClient client3 = azureStorageService.getSelectedClient("azure3", LocationMode.PRIMARY_ONLY);
@@ -131,13 +114,13 @@ public class AzureStorageServiceTests extends ESTestCase {
}
public void testGetSelectedClientNoTimeout() {
- AzureStorageServiceImpl azureStorageService = new AzureStorageServiceMockForSettings(buildSettings());
+ AzureStorageServiceImpl azureStorageService = createAzureService(buildSettings());
CloudBlobClient client1 = azureStorageService.getSelectedClient("azure1", LocationMode.PRIMARY_ONLY);
assertThat(client1.getDefaultRequestOptions().getTimeoutIntervalInMs(), is(nullValue()));
}
public void testGetSelectedClientBackoffPolicy() {
- AzureStorageServiceImpl azureStorageService = new AzureStorageServiceMockForSettings(buildSettings());
+ AzureStorageServiceImpl azureStorageService = createAzureService(buildSettings());
CloudBlobClient client1 = azureStorageService.getSelectedClient("azure1", LocationMode.PRIMARY_ONLY);
assertThat(client1.getDefaultRequestOptions().getRetryPolicyFactory(), is(notNullValue()));
assertThat(client1.getDefaultRequestOptions().getRetryPolicyFactory(), instanceOf(RetryExponentialRetry.class));
@@ -149,7 +132,7 @@ public class AzureStorageServiceTests extends ESTestCase {
.put("azure.client.azure1.max_retries", 7)
.build();
- AzureStorageServiceImpl azureStorageService = new AzureStorageServiceMockForSettings(timeoutSettings);
+ AzureStorageServiceImpl azureStorageService = createAzureService(timeoutSettings);
CloudBlobClient client1 = azureStorageService.getSelectedClient("azure1", LocationMode.PRIMARY_ONLY);
assertThat(client1.getDefaultRequestOptions().getRetryPolicyFactory(), is(notNullValue()));
assertThat(client1.getDefaultRequestOptions().getRetryPolicyFactory(), instanceOf(RetryExponentialRetry.class));
@@ -159,7 +142,7 @@ public class AzureStorageServiceTests extends ESTestCase {
Settings settings = Settings.builder()
.setSecureSettings(buildSecureSettings())
.build();
- AzureStorageServiceMockForSettings mock = new AzureStorageServiceMockForSettings(settings);
+ AzureStorageServiceImpl mock = createAzureService(settings);
assertThat(mock.storageSettings.get("azure1").getProxy(), nullValue());
assertThat(mock.storageSettings.get("azure2").getProxy(), nullValue());
assertThat(mock.storageSettings.get("azure3").getProxy(), nullValue());
@@ -172,7 +155,7 @@ public class AzureStorageServiceTests extends ESTestCase {
.put("azure.client.azure1.proxy.port", 8080)
.put("azure.client.azure1.proxy.type", "http")
.build();
- AzureStorageServiceMockForSettings mock = new AzureStorageServiceMockForSettings(settings);
+ AzureStorageServiceImpl mock = createAzureService(settings);
Proxy azure1Proxy = mock.storageSettings.get("azure1").getProxy();
assertThat(azure1Proxy, notNullValue());
@@ -192,7 +175,7 @@ public class AzureStorageServiceTests extends ESTestCase {
.put("azure.client.azure2.proxy.port", 8081)
.put("azure.client.azure2.proxy.type", "http")
.build();
- AzureStorageServiceMockForSettings mock = new AzureStorageServiceMockForSettings(settings);
+ AzureStorageServiceImpl mock = createAzureService(settings);
Proxy azure1Proxy = mock.storageSettings.get("azure1").getProxy();
assertThat(azure1Proxy, notNullValue());
assertThat(azure1Proxy.type(), is(Proxy.Type.HTTP));
@@ -211,7 +194,7 @@ public class AzureStorageServiceTests extends ESTestCase {
.put("azure.client.azure1.proxy.port", 8080)
.put("azure.client.azure1.proxy.type", "socks")
.build();
- AzureStorageServiceMockForSettings mock = new AzureStorageServiceMockForSettings(settings);
+ AzureStorageServiceImpl mock = createAzureService(settings);
Proxy azure1Proxy = mock.storageSettings.get("azure1").getProxy();
assertThat(azure1Proxy, notNullValue());
assertThat(azure1Proxy.type(), is(Proxy.Type.SOCKS));
@@ -227,7 +210,7 @@ public class AzureStorageServiceTests extends ESTestCase {
.put("azure.client.azure1.proxy.type", randomFrom("socks", "http"))
.build();
- SettingsException e = expectThrows(SettingsException.class, () -> new AzureStorageServiceMockForSettings(settings));
+ SettingsException e = expectThrows(SettingsException.class, () -> createAzureService(settings));
assertEquals("Azure Proxy type has been set but proxy host or port is not defined.", e.getMessage());
}
@@ -238,7 +221,7 @@ public class AzureStorageServiceTests extends ESTestCase {
.put("azure.client.azure1.proxy.type", randomFrom("socks", "http"))
.build();
- SettingsException e = expectThrows(SettingsException.class, () -> new AzureStorageServiceMockForSettings(settings));
+ SettingsException e = expectThrows(SettingsException.class, () -> createAzureService(settings));
assertEquals("Azure Proxy type has been set but proxy host or port is not defined.", e.getMessage());
}
@@ -249,7 +232,7 @@ public class AzureStorageServiceTests extends ESTestCase {
.put("azure.client.azure1.proxy.port", 8080)
.build();
- SettingsException e = expectThrows(SettingsException.class, () -> new AzureStorageServiceMockForSettings(settings));
+ SettingsException e = expectThrows(SettingsException.class, () -> createAzureService(settings));
assertEquals("Azure Proxy port or host have been set but proxy type is not defined.", e.getMessage());
}
@@ -261,26 +244,10 @@ public class AzureStorageServiceTests extends ESTestCase {
.put("azure.client.azure1.proxy.port", 8080)
.build();
- SettingsException e = expectThrows(SettingsException.class, () -> new AzureStorageServiceMockForSettings(settings));
+ SettingsException e = expectThrows(SettingsException.class, () -> createAzureService(settings));
assertEquals("Azure proxy host is unknown.", e.getMessage());
}
- /**
- * This internal class just overload createClient method which is called by AzureStorageServiceImpl.doStart()
- */
- class AzureStorageServiceMockForSettings extends AzureStorageServiceImpl {
- AzureStorageServiceMockForSettings(Settings settings) {
- super(settings, AzureStorageSettings.load(settings));
- }
-
- // We fake the client here
- @Override
- void createClient(AzureStorageSettings azureStorageSettings) {
- this.clients.put(azureStorageSettings.getAccount(),
- new CloudBlobClient(URI.create("https://" + azureStorageSettings.getAccount())));
- }
- }
-
public void testBlobNameFromUri() throws URISyntaxException {
String name = blobNameFromUri(new URI("https://myservice.azure.net/container/path/to/myfile"));
assertThat(name, is("path/to/myfile"));
@@ -291,4 +258,27 @@ public class AzureStorageServiceTests extends ESTestCase {
name = blobNameFromUri(new URI("https://127.0.0.1/container/path/to/myfile"));
assertThat(name, is("path/to/myfile"));
}
+
+ private static MockSecureSettings buildSecureSettings() {
+ MockSecureSettings secureSettings = new MockSecureSettings();
+ secureSettings.setString("azure.client.azure1.account", "myaccount1");
+ secureSettings.setString("azure.client.azure1.key", encodeKey("mykey1"));
+ secureSettings.setString("azure.client.azure2.account", "myaccount2");
+ secureSettings.setString("azure.client.azure2.key", encodeKey("mykey2"));
+ secureSettings.setString("azure.client.azure3.account", "myaccount3");
+ secureSettings.setString("azure.client.azure3.key", encodeKey("mykey3"));
+ return secureSettings;
+ }
+
+ private static Settings buildSettings() {
+ return Settings.builder().setSecureSettings(buildSecureSettings()).build();
+ }
+
+ private static AzureStorageServiceImpl createAzureService(final Settings settings) {
+ return new AzureStorageServiceImpl(settings, AzureStorageSettings.load(settings));
+ }
+
+ private static String encodeKey(final String value) {
+ return Base64.encode(value.getBytes(StandardCharsets.UTF_8));
+ }
}
diff --git a/plugins/transport-nio/src/main/java/org/elasticsearch/http/nio/NioHttpServerTransport.java b/plugins/transport-nio/src/main/java/org/elasticsearch/http/nio/NioHttpServerTransport.java
index 825a023bd51..de5c166de3f 100644
--- a/plugins/transport-nio/src/main/java/org/elasticsearch/http/nio/NioHttpServerTransport.java
+++ b/plugins/transport-nio/src/main/java/org/elasticsearch/http/nio/NioHttpServerTransport.java
@@ -42,7 +42,7 @@ import org.elasticsearch.http.BindHttpException;
import org.elasticsearch.http.HttpHandlingSettings;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.http.HttpStats;
-import org.elasticsearch.http.netty4.AbstractHttpServerTransport;
+import org.elasticsearch.http.AbstractHttpServerTransport;
import org.elasticsearch.nio.AcceptingSelector;
import org.elasticsearch.nio.AcceptorEventHandler;
import org.elasticsearch.nio.BytesChannelContext;
diff --git a/qa/vagrant/src/test/resources/packaging/tests/20_tar_package.bats b/qa/vagrant/src/test/resources/packaging/tests/20_tar_package.bats
index 1a3704c3317..3607e4ab45a 100644
--- a/qa/vagrant/src/test/resources/packaging/tests/20_tar_package.bats
+++ b/qa/vagrant/src/test/resources/packaging/tests/20_tar_package.bats
@@ -68,6 +68,7 @@ setup() {
@test "[TAR] install archive" {
# Install the archive
install_archive
+ set_debug_logging
count=$(find /tmp -type d -name 'elasticsearch*' | wc -l)
[ "$count" -eq 1 ]
diff --git a/qa/vagrant/src/test/resources/packaging/tests/module_and_plugin_test_cases.bash b/qa/vagrant/src/test/resources/packaging/tests/module_and_plugin_test_cases.bash
index 79228adfee5..e258c4db5e6 100644
--- a/qa/vagrant/src/test/resources/packaging/tests/module_and_plugin_test_cases.bash
+++ b/qa/vagrant/src/test/resources/packaging/tests/module_and_plugin_test_cases.bash
@@ -61,6 +61,7 @@ setup() {
[ ! -d "$ESHOME" ]; then
clean_before_test
install
+ set_debug_logging
fi
}
diff --git a/qa/vagrant/src/test/resources/packaging/utils/utils.bash b/qa/vagrant/src/test/resources/packaging/utils/utils.bash
index 4e3fdf5bd55..f8c3005de6c 100644
--- a/qa/vagrant/src/test/resources/packaging/utils/utils.bash
+++ b/qa/vagrant/src/test/resources/packaging/utils/utils.bash
@@ -461,6 +461,13 @@ debug_collect_logs() {
describe_port 127.0.0.1 9201
}
+set_debug_logging() {
+ if [ "$ESCONFIG" ] && [ -d "$ESCONFIG" ] && [ -f /etc/os-release ] && (grep -qi suse /etc/os-release); then
+ echo 'logger.org.elasticsearch.indices: DEBUG' >> "$ESCONFIG/elasticsearch.yml"
+ echo 'logger.org.elasticsearch.gateway: TRACE' >> "$ESCONFIG/elasticsearch.yml"
+ fi
+}
+
# Waits for Elasticsearch to reach some status.
# $1 - expected status - defaults to green
wait_for_elasticsearch_status() {
diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.analyze/10_analyze.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.analyze/10_analyze.yml
index d95417c16ca..85861a23d59 100644
--- a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.analyze/10_analyze.yml
+++ b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.analyze/10_analyze.yml
@@ -75,19 +75,3 @@
- match: { detail.tokenizer.tokens.2.token: buzz }
- match: { detail.tokenfilters.0.name: "_anonymous_tokenfilter" }
- match: { detail.tokenfilters.0.tokens.0.token: bar }
-
----
-"Custom normalizer in request":
- - do:
- indices.analyze:
- body:
- text: ABc
- explain: true
- filter: ["lowercase"]
-
- - length: { detail.tokenizer.tokens: 1 }
- - length: { detail.tokenfilters.0.tokens: 1 }
- - match: { detail.tokenizer.name: keyword_for_normalizer }
- - match: { detail.tokenizer.tokens.0.token: ABc }
- - match: { detail.tokenfilters.0.name: lowercase }
- - match: { detail.tokenfilters.0.tokens.0.token: abc }
diff --git a/server/licenses/lucene-analyzers-common-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-analyzers-common-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..82585bb7ff3
--- /dev/null
+++ b/server/licenses/lucene-analyzers-common-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+0f75703c30756c31f7d09ec79191dab6fb35c958
\ No newline at end of file
diff --git a/server/licenses/lucene-analyzers-common-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-analyzers-common-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 1c471a77d80..00000000000
--- a/server/licenses/lucene-analyzers-common-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-96ab108569c77932ecb17c45421affece207df5c
\ No newline at end of file
diff --git a/server/licenses/lucene-backward-codecs-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-backward-codecs-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..981e6d1a173
--- /dev/null
+++ b/server/licenses/lucene-backward-codecs-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+c5c519fdea65726612f79e3dd942b7316966646e
\ No newline at end of file
diff --git a/server/licenses/lucene-backward-codecs-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-backward-codecs-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 4c8842872ab..00000000000
--- a/server/licenses/lucene-backward-codecs-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-72d09ca50979f716a57f53f2de33d55023a166ec
\ No newline at end of file
diff --git a/server/licenses/lucene-core-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-core-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..cea13d14fe1
--- /dev/null
+++ b/server/licenses/lucene-core-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+f345b6aa3c550dafc63de3e5a5c404691e782336
\ No newline at end of file
diff --git a/server/licenses/lucene-core-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-core-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 4aecfc6a550..00000000000
--- a/server/licenses/lucene-core-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e118e4d05070378516b9055184b74498ba528dee
\ No newline at end of file
diff --git a/server/licenses/lucene-grouping-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-grouping-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..fcb173608ef
--- /dev/null
+++ b/server/licenses/lucene-grouping-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+7a74855e37124a27af36390c9d15abe33614129e
\ No newline at end of file
diff --git a/server/licenses/lucene-grouping-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-grouping-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 948aacf662f..00000000000
--- a/server/licenses/lucene-grouping-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2b2ea6bfe6fa159bbf205bf7f7fa2ed2c22bbffc
\ No newline at end of file
diff --git a/server/licenses/lucene-highlighter-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-highlighter-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..79addefbfc6
--- /dev/null
+++ b/server/licenses/lucene-highlighter-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+0e3df4b469465ef101254fdcbb08ebd8a19f1f9d
\ No newline at end of file
diff --git a/server/licenses/lucene-highlighter-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-highlighter-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 30a960c5a80..00000000000
--- a/server/licenses/lucene-highlighter-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-423e4fff9276101d845d6073dc6cd27504def207
\ No newline at end of file
diff --git a/server/licenses/lucene-join-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-join-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..a9838db7caa
--- /dev/null
+++ b/server/licenses/lucene-join-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+05d236149c99c860e6b627a8f78ea32918c108c3
\ No newline at end of file
diff --git a/server/licenses/lucene-join-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-join-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index fb3cd72c755..00000000000
--- a/server/licenses/lucene-join-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-27561038da2edcae3ecc3a08b0a52824966af87a
\ No newline at end of file
diff --git a/server/licenses/lucene-memory-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-memory-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..679c79788f5
--- /dev/null
+++ b/server/licenses/lucene-memory-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+d83e7e65eb268425f7bd5be2425d4a00b556bc47
\ No newline at end of file
diff --git a/server/licenses/lucene-memory-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-memory-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index cd989836ab2..00000000000
--- a/server/licenses/lucene-memory-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d7d422159f705261784d121e24877119d9c95083
\ No newline at end of file
diff --git a/server/licenses/lucene-misc-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-misc-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..c403d4c4f86
--- /dev/null
+++ b/server/licenses/lucene-misc-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+440a998b5bf99871bec4272a219de01b25751d5c
\ No newline at end of file
diff --git a/server/licenses/lucene-misc-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-misc-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index c4d8ad61c73..00000000000
--- a/server/licenses/lucene-misc-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fc09508fde6ba87f241d7e3148d9e310c0db9cb9
\ No newline at end of file
diff --git a/server/licenses/lucene-queries-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-queries-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..6b8897d1ae7
--- /dev/null
+++ b/server/licenses/lucene-queries-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+2a5c031155fdfa743af321150c0dd654a6ea3c71
\ No newline at end of file
diff --git a/server/licenses/lucene-queries-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-queries-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 0cb51736803..00000000000
--- a/server/licenses/lucene-queries-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-201fdf3432ff3fef0f48c38c2c0f482c144f6868
\ No newline at end of file
diff --git a/server/licenses/lucene-queryparser-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-queryparser-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..b6c6bf76610
--- /dev/null
+++ b/server/licenses/lucene-queryparser-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+d021c9a461ff0f020d038ad5ecc5127973d4674a
\ No newline at end of file
diff --git a/server/licenses/lucene-queryparser-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-queryparser-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index ecd6440ba64..00000000000
--- a/server/licenses/lucene-queryparser-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-917df8c8d08952a012a34050b183b6204ae7081b
\ No newline at end of file
diff --git a/server/licenses/lucene-sandbox-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-sandbox-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..92f64fca2c7
--- /dev/null
+++ b/server/licenses/lucene-sandbox-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+9877a14c53e69b39fff2bf10d49a61171746d940
\ No newline at end of file
diff --git a/server/licenses/lucene-sandbox-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-sandbox-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 3e65eaeef91..00000000000
--- a/server/licenses/lucene-sandbox-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-caff84fa66cb0376835c39f3d4ca7dfd2177d8f4
\ No newline at end of file
diff --git a/server/licenses/lucene-spatial-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-spatial-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..2f691988c44
--- /dev/null
+++ b/server/licenses/lucene-spatial-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+7d7e5101b46a120efa311509948c0d1f9bf30155
\ No newline at end of file
diff --git a/server/licenses/lucene-spatial-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-spatial-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index c86854b16c3..00000000000
--- a/server/licenses/lucene-spatial-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e1bce61a9d9129a8d0fdd3127a84665d29f53eb0
\ No newline at end of file
diff --git a/server/licenses/lucene-spatial-extras-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-spatial-extras-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..86c147f9610
--- /dev/null
+++ b/server/licenses/lucene-spatial-extras-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+5a4c11db96ae70b9048243cc530fcbc76faa0978
\ No newline at end of file
diff --git a/server/licenses/lucene-spatial-extras-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-spatial-extras-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 144984a3869..00000000000
--- a/server/licenses/lucene-spatial-extras-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3a2e4373d79fda968a078971efa2cb8ec9ff65b0
\ No newline at end of file
diff --git a/server/licenses/lucene-spatial3d-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-spatial3d-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..2fbdcdecf1a
--- /dev/null
+++ b/server/licenses/lucene-spatial3d-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+afb01af1450067b145ca2c1d737b5907288af560
\ No newline at end of file
diff --git a/server/licenses/lucene-spatial3d-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-spatial3d-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index fd19f4ad811..00000000000
--- a/server/licenses/lucene-spatial3d-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7f14927e5c3c1c85c4c5b3681c28c5e36f241dda
\ No newline at end of file
diff --git a/server/licenses/lucene-suggest-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/server/licenses/lucene-suggest-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..1a86525735c
--- /dev/null
+++ b/server/licenses/lucene-suggest-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+473f0221e0b2ea45940d8ae6dcf16e39c81b18c2
\ No newline at end of file
diff --git a/server/licenses/lucene-suggest-7.4.0-snapshot-cc2ee23050.jar.sha1 b/server/licenses/lucene-suggest-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index ba405960dbe..00000000000
--- a/server/licenses/lucene-suggest-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-6e708a38c957a655e0cfedb06a1b9aa892929db0
\ No newline at end of file
diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java
index c0d254509c1..ae58d2885bb 100644
--- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java
+++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaData.java
@@ -270,7 +270,8 @@ public class IndexTemplateMetaData extends AbstractDiffable VALID_FIELDS = Sets.newHashSet("template", "order", "mappings", "settings", "index_patterns");
+ private static final Set VALID_FIELDS = Sets.newHashSet(
+ "template", "order", "mappings", "settings", "index_patterns", "aliases", "version");
static {
VALID_FIELDS.addAll(IndexMetaData.customPrototypes.keySet());
}
diff --git a/server/src/main/java/org/elasticsearch/http/netty4/AbstractHttpServerTransport.java b/server/src/main/java/org/elasticsearch/http/AbstractHttpServerTransport.java
similarity index 98%
rename from server/src/main/java/org/elasticsearch/http/netty4/AbstractHttpServerTransport.java
rename to server/src/main/java/org/elasticsearch/http/AbstractHttpServerTransport.java
index a0b3632310b..c75754bde58 100644
--- a/server/src/main/java/org/elasticsearch/http/netty4/AbstractHttpServerTransport.java
+++ b/server/src/main/java/org/elasticsearch/http/AbstractHttpServerTransport.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.elasticsearch.http.netty4;
+package org.elasticsearch.http;
import com.carrotsearch.hppc.IntHashSet;
import com.carrotsearch.hppc.IntSet;
@@ -30,8 +30,6 @@ import org.elasticsearch.common.transport.PortsRange;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.util.concurrent.ThreadContext;
-import org.elasticsearch.http.BindHttpException;
-import org.elasticsearch.http.HttpInfo;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.threadpool.ThreadPool;
diff --git a/server/src/main/java/org/elasticsearch/index/analysis/AnalysisRegistry.java b/server/src/main/java/org/elasticsearch/index/analysis/AnalysisRegistry.java
index 63e56651cd0..77be68fbbe2 100644
--- a/server/src/main/java/org/elasticsearch/index/analysis/AnalysisRegistry.java
+++ b/server/src/main/java/org/elasticsearch/index/analysis/AnalysisRegistry.java
@@ -548,6 +548,10 @@ public final class AnalysisRegistry implements Closeable {
TokenizerFactory keywordTokenizerFactory,
Map tokenFilters,
Map charFilters) {
+ if (keywordTokenizerFactory == null) {
+ throw new IllegalStateException("keyword tokenizer factory is null, normalizers require analysis-common module");
+ }
+
if (normalizerFactory instanceof CustomNormalizerProvider) {
((CustomNormalizerProvider) normalizerFactory).build(keywordTokenizerFactory, charFilters, tokenFilters);
}
diff --git a/server/src/main/java/org/elasticsearch/index/shard/ElasticsearchMergePolicy.java b/server/src/main/java/org/elasticsearch/index/shard/ElasticsearchMergePolicy.java
index e49ac868aa7..430e75ed494 100644
--- a/server/src/main/java/org/elasticsearch/index/shard/ElasticsearchMergePolicy.java
+++ b/server/src/main/java/org/elasticsearch/index/shard/ElasticsearchMergePolicy.java
@@ -83,7 +83,7 @@ public final class ElasticsearchMergePolicy extends FilterMergePolicy {
@Override
public MergeSpecification findForcedMerges(SegmentInfos segmentInfos,
- int maxSegmentCount, Map segmentsToMerge, IndexWriter writer)
+ int maxSegmentCount, Map segmentsToMerge, MergeContext mergeContext)
throws IOException {
if (upgradeInProgress) {
@@ -122,7 +122,7 @@ public final class ElasticsearchMergePolicy extends FilterMergePolicy {
// has a chance to decide what to do (e.g. collapse the segments to satisfy maxSegmentCount)
}
- return super.findForcedMerges(segmentInfos, maxSegmentCount, segmentsToMerge, writer);
+ return super.findForcedMerges(segmentInfos, maxSegmentCount, segmentsToMerge, mergeContext);
}
/**
diff --git a/server/src/main/java/org/elasticsearch/indices/analysis/AnalysisModule.java b/server/src/main/java/org/elasticsearch/indices/analysis/AnalysisModule.java
index 10547444226..bc590381c3c 100644
--- a/server/src/main/java/org/elasticsearch/indices/analysis/AnalysisModule.java
+++ b/server/src/main/java/org/elasticsearch/indices/analysis/AnalysisModule.java
@@ -56,7 +56,6 @@ import org.elasticsearch.index.analysis.IndonesianAnalyzerProvider;
import org.elasticsearch.index.analysis.IrishAnalyzerProvider;
import org.elasticsearch.index.analysis.ItalianAnalyzerProvider;
import org.elasticsearch.index.analysis.KeywordAnalyzerProvider;
-import org.elasticsearch.index.analysis.KeywordTokenizerFactory;
import org.elasticsearch.index.analysis.LatvianAnalyzerProvider;
import org.elasticsearch.index.analysis.LithuanianAnalyzerProvider;
import org.elasticsearch.index.analysis.NorwegianAnalyzerProvider;
@@ -225,7 +224,6 @@ public final class AnalysisModule {
private NamedRegistry> setupTokenizers(List plugins) {
NamedRegistry> tokenizers = new NamedRegistry<>("tokenizer");
tokenizers.register("standard", StandardTokenizerFactory::new);
- tokenizers.register("keyword", KeywordTokenizerFactory::new);
tokenizers.extractAndRegister(plugins, AnalysisPlugin::getTokenizers);
return tokenizers;
}
diff --git a/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java b/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java
index da6dad1dff3..11f8769c86b 100644
--- a/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java
+++ b/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java
@@ -74,6 +74,11 @@ public class StoredScriptSource extends AbstractDiffable imp
*/
public static final ParseField TEMPLATE_PARSE_FIELD = new ParseField("template");
+ /**
+ * Standard {@link ParseField} for query on the inner field.
+ */
+ public static final ParseField TEMPLATE_NO_WRAPPER_PARSE_FIELD = new ParseField("query");
+
/**
* Standard {@link ParseField} for lang on the inner level.
*/
@@ -189,6 +194,26 @@ public class StoredScriptSource extends AbstractDiffable imp
PARSER.declareField(Builder::setOptions, XContentParser::mapStrings, OPTIONS_PARSE_FIELD, ValueType.OBJECT);
}
+ private static StoredScriptSource parseRemaining(Token token, XContentParser parser) throws IOException {
+ try (XContentBuilder builder = XContentFactory.jsonBuilder()) {
+ if (token != Token.START_OBJECT) {
+ builder.startObject();
+ builder.copyCurrentStructure(parser);
+ builder.endObject();
+ } else {
+ builder.copyCurrentStructure(parser);
+ }
+
+ String source = Strings.toString(builder);
+
+ if (source == null || source.isEmpty()) {
+ DEPRECATION_LOGGER.deprecated("empty templates should no longer be used");
+ }
+
+ return new StoredScriptSource(Script.DEFAULT_TEMPLATE_LANG, source, Collections.emptyMap());
+ }
+ }
+
/**
* This will parse XContent into a {@link StoredScriptSource}. The following formats can be parsed:
*
@@ -304,38 +329,28 @@ public class StoredScriptSource extends AbstractDiffable imp
} else {
throw new ParsingException(parser.getTokenLocation(), "unexpected token [" + token + "], expected [{, ]");
}
- } else {
- if (TEMPLATE_PARSE_FIELD.getPreferredName().equals(name)) {
- token = parser.nextToken();
+ } else if (TEMPLATE_PARSE_FIELD.getPreferredName().equals(name)) {
- if (token == Token.VALUE_STRING) {
- String source = parser.text();
+ DEPRECATION_LOGGER.deprecated("the template context is now deprecated. Specify templates in a \"script\" element.");
- if (source == null || source.isEmpty()) {
- DEPRECATION_LOGGER.deprecated("empty templates should no longer be used");
- }
-
- return new StoredScriptSource(Script.DEFAULT_TEMPLATE_LANG, source, Collections.emptyMap());
- }
- }
-
- try (XContentBuilder builder = XContentFactory.jsonBuilder()) {
- if (token != Token.START_OBJECT) {
- builder.startObject();
- builder.copyCurrentStructure(parser);
- builder.endObject();
- } else {
- builder.copyCurrentStructure(parser);
- }
-
- String source = Strings.toString(builder);
+ token = parser.nextToken();
+ if (token == Token.VALUE_STRING) {
+ String source = parser.text();
if (source == null || source.isEmpty()) {
DEPRECATION_LOGGER.deprecated("empty templates should no longer be used");
}
return new StoredScriptSource(Script.DEFAULT_TEMPLATE_LANG, source, Collections.emptyMap());
+ } else {
+ return parseRemaining(token, parser);
}
+ } else if (TEMPLATE_NO_WRAPPER_PARSE_FIELD.getPreferredName().equals(name)) {
+ DEPRECATION_LOGGER.deprecated("the template context is now deprecated. Specify templates in a \"script\" element.");
+ return parseRemaining(token, parser);
+ } else {
+ DEPRECATION_LOGGER.deprecated("scripts should not be stored without a context. Specify them in a \"script\" element.");
+ return parseRemaining(token, parser);
}
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/TransportAnalyzeActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/TransportAnalyzeActionTests.java
index de11902d914..c0404a47ab2 100644
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/TransportAnalyzeActionTests.java
+++ b/server/src/test/java/org/elasticsearch/action/admin/indices/TransportAnalyzeActionTests.java
@@ -19,6 +19,7 @@
package org.elasticsearch.action.admin.indices;
import org.apache.lucene.analysis.MockTokenFilter;
+import org.apache.lucene.analysis.MockTokenizer;
import org.apache.lucene.analysis.TokenStream;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
@@ -37,6 +38,7 @@ import org.elasticsearch.index.analysis.CharFilterFactory;
import org.elasticsearch.index.analysis.IndexAnalyzers;
import org.elasticsearch.index.analysis.PreConfiguredCharFilter;
import org.elasticsearch.index.analysis.TokenFilterFactory;
+import org.elasticsearch.index.analysis.TokenizerFactory;
import org.elasticsearch.indices.analysis.AnalysisModule;
import org.elasticsearch.indices.analysis.AnalysisModule.AnalysisProvider;
import org.elasticsearch.indices.analysis.AnalysisModuleTests.AppendCharFilter;
@@ -107,6 +109,12 @@ public class TransportAnalyzeActionTests extends ESTestCase {
return singletonMap("append", AppendCharFilterFactory::new);
}
+ @Override
+ public Map> getTokenizers() {
+ return singletonMap("keyword", (indexSettings, environment, name, settings) ->
+ () -> new MockTokenizer(MockTokenizer.KEYWORD, false));
+ }
+
@Override
public Map> getTokenFilters() {
return singletonMap("mock", MockFactory::new);
diff --git a/server/src/test/java/org/elasticsearch/action/termvectors/GetTermVectorsIT.java b/server/src/test/java/org/elasticsearch/action/termvectors/GetTermVectorsIT.java
index c55e4851edb..b5a596401cb 100644
--- a/server/src/test/java/org/elasticsearch/action/termvectors/GetTermVectorsIT.java
+++ b/server/src/test/java/org/elasticsearch/action/termvectors/GetTermVectorsIT.java
@@ -37,10 +37,13 @@ import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.engine.VersionConflictEngineException;
import org.elasticsearch.index.mapper.FieldMapper;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.test.MockKeywordPlugin;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -58,6 +61,12 @@ import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
public class GetTermVectorsIT extends AbstractTermVectorsTestCase {
+
+ @Override
+ protected Collection> nodePlugins() {
+ return Collections.singleton(MockKeywordPlugin.class);
+ }
+
public void testNoSuchDoc() throws Exception {
XContentBuilder mapping = jsonBuilder().startObject().startObject("type1")
.startObject("properties")
diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java
index d6eb00c499e..6d489f5feb3 100644
--- a/server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java
+++ b/server/src/test/java/org/elasticsearch/cluster/metadata/IndexTemplateMetaDataTests.java
@@ -43,6 +43,7 @@ import java.util.Collections;
import static java.util.Collections.singletonMap;
import static org.elasticsearch.cluster.metadata.AliasMetaData.newAliasMetaDataBuilder;
import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.Matchers.contains;
public class IndexTemplateMetaDataTests extends ESTestCase {
@@ -167,4 +168,54 @@ public class IndexTemplateMetaDataTests extends ESTestCase {
assertThat(ex.getMessage(), equalTo("Index patterns must not be null or empty; got null"));
}
}
+
+ public void testParseTemplateWithAliases() throws Exception {
+ String templateInJSON = "{\"aliases\": {\"log\":{}}, \"index_patterns\": [\"pattern-1\"]}";
+ try (XContentParser parser =
+ XContentHelper.createParser(NamedXContentRegistry.EMPTY,
+ DeprecationHandler.THROW_UNSUPPORTED_OPERATION, new BytesArray(templateInJSON), XContentType.JSON)) {
+ IndexTemplateMetaData template = IndexTemplateMetaData.Builder.fromXContent(parser, randomAlphaOfLengthBetween(1, 100));
+ assertThat(template.aliases().containsKey("log"), equalTo(true));
+ assertThat(template.patterns(), contains("pattern-1"));
+ }
+ }
+
+ public void testFromToXContent() throws Exception {
+ String templateName = randomUnicodeOfCodepointLengthBetween(1, 10);
+ IndexTemplateMetaData.Builder templateBuilder = IndexTemplateMetaData.builder(templateName);
+ templateBuilder.patterns(Arrays.asList("pattern-1"));
+ int numAlias = between(0, 5);
+ for (int i = 0; i < numAlias; i++) {
+ AliasMetaData.Builder alias = AliasMetaData.builder(randomRealisticUnicodeOfLengthBetween(1, 100));
+ if (randomBoolean()) {
+ alias.indexRouting(randomRealisticUnicodeOfLengthBetween(1, 100));
+ }
+ if (randomBoolean()) {
+ alias.searchRouting(randomRealisticUnicodeOfLengthBetween(1, 100));
+ }
+ templateBuilder.putAlias(alias);
+ }
+ if (randomBoolean()) {
+ templateBuilder.settings(Settings.builder().put("index.setting-1", randomLong()));
+ templateBuilder.settings(Settings.builder().put("index.setting-2", randomTimeValue()));
+ }
+ if (randomBoolean()) {
+ templateBuilder.order(randomInt());
+ }
+ if (randomBoolean()) {
+ templateBuilder.version(between(0, 100));
+ }
+ if (randomBoolean()) {
+ templateBuilder.putMapping("doc", "{\"doc\":{\"properties\":{\"type\":\"text\"}}}");
+ }
+ IndexTemplateMetaData template = templateBuilder.build();
+ XContentBuilder builder = XContentBuilder.builder(randomFrom(XContentType.JSON.xContent()));
+ builder.startObject();
+ IndexTemplateMetaData.Builder.toXContent(template, builder, ToXContent.EMPTY_PARAMS);
+ builder.endObject();
+ try (XContentParser parser = createParser(shuffleXContent(builder))) {
+ IndexTemplateMetaData parsed = IndexTemplateMetaData.Builder.fromXContent(parser, templateName);
+ assertThat(parsed, equalTo(template));
+ }
+ }
}
diff --git a/server/src/test/java/org/elasticsearch/gateway/GatewayIndexStateIT.java b/server/src/test/java/org/elasticsearch/gateway/GatewayIndexStateIT.java
index aeadcf30e36..209fbd37c59 100644
--- a/server/src/test/java/org/elasticsearch/gateway/GatewayIndexStateIT.java
+++ b/server/src/test/java/org/elasticsearch/gateway/GatewayIndexStateIT.java
@@ -432,7 +432,7 @@ public class GatewayIndexStateIT extends ESIntegTestCase {
logger.info("--> starting one node");
internalCluster().startNode();
prepareCreate("test").setSettings(Settings.builder()
- .put("index.analysis.analyzer.test.tokenizer", "keyword")
+ .put("index.analysis.analyzer.test.tokenizer", "standard")
.put("index.number_of_shards", "1"))
.addMapping("type1", "{\n" +
" \"type1\": {\n" +
diff --git a/modules/transport-netty4/src/test/java/org/elasticsearch/http/netty4/Netty4HttpPublishPortTests.java b/server/src/test/java/org/elasticsearch/http/AbstractHttpServerTransportTests.java
similarity index 93%
rename from modules/transport-netty4/src/test/java/org/elasticsearch/http/netty4/Netty4HttpPublishPortTests.java
rename to server/src/test/java/org/elasticsearch/http/AbstractHttpServerTransportTests.java
index afa513275ea..ee74d98002f 100644
--- a/modules/transport-netty4/src/test/java/org/elasticsearch/http/netty4/Netty4HttpPublishPortTests.java
+++ b/server/src/test/java/org/elasticsearch/http/AbstractHttpServerTransportTests.java
@@ -17,13 +17,11 @@
* under the License.
*/
-package org.elasticsearch.http.netty4;
+package org.elasticsearch.http;
import org.elasticsearch.common.network.NetworkUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
-import org.elasticsearch.http.BindHttpException;
-import org.elasticsearch.http.HttpTransportSettings;
import org.elasticsearch.test.ESTestCase;
import java.net.UnknownHostException;
@@ -32,11 +30,11 @@ import java.util.List;
import static java.net.InetAddress.getByName;
import static java.util.Arrays.asList;
-import static org.elasticsearch.http.netty4.Netty4HttpServerTransport.resolvePublishPort;
+import static org.elasticsearch.http.AbstractHttpServerTransport.resolvePublishPort;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
-public class Netty4HttpPublishPortTests extends ESTestCase {
+public class AbstractHttpServerTransportTests extends ESTestCase {
public void testHttpPublishPort() throws Exception {
int boundPort = randomIntBetween(9000, 9100);
@@ -88,5 +86,4 @@ public class Netty4HttpPublishPortTests extends ESTestCase {
}
return addresses;
}
-
}
diff --git a/server/src/test/java/org/elasticsearch/index/analysis/CustomNormalizerTests.java b/server/src/test/java/org/elasticsearch/index/analysis/CustomNormalizerTests.java
index 7d8d64e6962..e2025145241 100644
--- a/server/src/test/java/org/elasticsearch/index/analysis/CustomNormalizerTests.java
+++ b/server/src/test/java/org/elasticsearch/index/analysis/CustomNormalizerTests.java
@@ -20,6 +20,8 @@
package org.elasticsearch.index.analysis;
import org.apache.lucene.analysis.MockLowerCaseFilter;
+import org.apache.lucene.analysis.MockTokenizer;
+import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
@@ -71,7 +73,7 @@ public class CustomNormalizerTests extends ESTokenStreamTestCase {
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
.build();
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
- () -> AnalysisTestsHelper.createTestAnalysisFromSettings(settings));
+ () -> AnalysisTestsHelper.createTestAnalysisFromSettings(settings, MOCK_ANALYSIS_PLUGIN));
assertEquals("Custom normalizer [my_normalizer] cannot configure a tokenizer", e.getMessage());
}
@@ -135,7 +137,7 @@ public class CustomNormalizerTests extends ESTokenStreamTestCase {
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
int result = reader.read(cbuf, off, len);
- for (int i = off; i < result; i++) {
+ for (int i = off; i < off + len; i++) {
if (cbuf[i] == 'a') {
cbuf[i] = 'z';
}
@@ -157,5 +159,11 @@ public class CustomNormalizerTests extends ESTokenStreamTestCase {
return new Factory();
});
}
+
+ @Override
+ public Map> getTokenizers() {
+ return singletonMap("keyword", (indexSettings, environment, name, settings) ->
+ () -> new MockTokenizer(MockTokenizer.KEYWORD, false));
+ }
}
}
diff --git a/server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldMapperTests.java
index bffb1737eeb..86cf7b4b766 100644
--- a/server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldMapperTests.java
+++ b/server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldMapperTests.java
@@ -20,6 +20,8 @@
package org.elasticsearch.index.mapper;
import org.apache.lucene.analysis.MockLowerCaseFilter;
+import org.apache.lucene.analysis.MockTokenizer;
+import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField;
@@ -33,7 +35,9 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.analysis.PreConfiguredTokenFilter;
+import org.elasticsearch.index.analysis.TokenizerFactory;
import org.elasticsearch.index.mapper.MapperService.MergeReason;
+import org.elasticsearch.indices.analysis.AnalysisModule;
import org.elasticsearch.plugins.AnalysisPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESSingleNodeTestCase;
@@ -44,8 +48,10 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
@@ -58,6 +64,21 @@ public class KeywordFieldMapperTests extends ESSingleNodeTestCase {
public List getPreConfiguredTokenFilters() {
return singletonList(PreConfiguredTokenFilter.singleton("mock_other_lowercase", true, MockLowerCaseFilter::new));
}
+
+ @Override
+ public Map> getTokenizers() {
+ return singletonMap("keyword", (indexSettings, environment, name, settings) -> {
+ class Factory implements TokenizerFactory {
+
+ @Override
+ public Tokenizer create() {
+ return new MockTokenizer(MockTokenizer.KEYWORD, false);
+ }
+ }
+ return new Factory();
+ });
+ }
+
};
@Override
diff --git a/server/src/test/java/org/elasticsearch/indices/analysis/AnalysisModuleTests.java b/server/src/test/java/org/elasticsearch/indices/analysis/AnalysisModuleTests.java
index 2bc98885f90..a31dcc81f72 100644
--- a/server/src/test/java/org/elasticsearch/indices/analysis/AnalysisModuleTests.java
+++ b/server/src/test/java/org/elasticsearch/indices/analysis/AnalysisModuleTests.java
@@ -21,6 +21,7 @@ package org.elasticsearch.indices.analysis;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.CharFilter;
+import org.apache.lucene.analysis.MockTokenizer;
import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
@@ -31,6 +32,7 @@ import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
+import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.env.Environment;
@@ -49,6 +51,7 @@ import org.elasticsearch.index.analysis.StandardTokenizerFactory;
import org.elasticsearch.index.analysis.StopTokenFilterFactory;
import org.elasticsearch.index.analysis.TokenFilterFactory;
import org.elasticsearch.index.analysis.MyFilterTokenFilterFactory;
+import org.elasticsearch.index.analysis.TokenizerFactory;
import org.elasticsearch.indices.analysis.AnalysisModule.AnalysisProvider;
import org.elasticsearch.plugins.AnalysisPlugin;
import org.elasticsearch.test.ESTestCase;
@@ -60,6 +63,8 @@ import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
+import java.io.StringReader;
+import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -222,7 +227,7 @@ public class AnalysisModuleTests extends ESTestCase {
public void testUnderscoreInAnalyzerName() throws IOException {
Settings settings = Settings.builder()
- .put("index.analysis.analyzer._invalid_name.tokenizer", "keyword")
+ .put("index.analysis.analyzer._invalid_name.tokenizer", "standard")
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
.put(IndexMetaData.SETTING_VERSION_CREATED, "1")
.build();
@@ -256,6 +261,13 @@ public class AnalysisModuleTests extends ESTestCase {
(tokenStream, esVersion) -> new AppendCharFilter(tokenStream, esVersion.toString()))
);
}
+
+ @Override
+ public Map> getTokenizers() {
+ // Need mock keyword tokenizer here, because alpha / beta versions are broken up by the dash.
+ return singletonMap("keyword", (indexSettings, environment, name, settings) ->
+ () -> new MockTokenizer(MockTokenizer.KEYWORD, false));
+ }
})).getAnalysisRegistry();
Version version = VersionUtils.randomVersion(random());
@@ -305,11 +317,11 @@ public class AnalysisModuleTests extends ESTestCase {
Version version = VersionUtils.randomVersion(random());
IndexAnalyzers analyzers = getIndexAnalyzers(registry, Settings.builder()
- .put("index.analysis.analyzer.no_version.tokenizer", "keyword")
+ .put("index.analysis.analyzer.no_version.tokenizer", "standard")
.put("index.analysis.analyzer.no_version.filter", "no_version")
- .put("index.analysis.analyzer.lucene_version.tokenizer", "keyword")
+ .put("index.analysis.analyzer.lucene_version.tokenizer", "standard")
.put("index.analysis.analyzer.lucene_version.filter", "lucene_version")
- .put("index.analysis.analyzer.elasticsearch_version.tokenizer", "keyword")
+ .put("index.analysis.analyzer.elasticsearch_version.tokenizer", "standard")
.put("index.analysis.analyzer.elasticsearch_version.filter", "elasticsearch_version")
.put(IndexMetaData.SETTING_VERSION_CREATED, version)
.build());
@@ -425,12 +437,17 @@ public class AnalysisModuleTests extends ESTestCase {
// Simple char filter that appends text to the term
public static class AppendCharFilter extends CharFilter {
- private final char[] appendMe;
- private int offsetInAppendMe = -1;
+
+ static Reader append(Reader input, String appendMe) {
+ try {
+ return new StringReader(Streams.copyToString(input) + appendMe);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
public AppendCharFilter(Reader input, String appendMe) {
- super(input);
- this.appendMe = appendMe.toCharArray();
+ super(append(input, appendMe));
}
@Override
@@ -440,24 +457,7 @@ public class AnalysisModuleTests extends ESTestCase {
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
- if (offsetInAppendMe < 0) {
- int read = input.read(cbuf, off, len);
- if (read == len) {
- return read;
- }
- off += read;
- len -= read;
- int allowedLen = Math.min(len, appendMe.length);
- System.arraycopy(appendMe, 0, cbuf, off, allowedLen);
- offsetInAppendMe = allowedLen;
- return read + allowedLen;
- }
- if (offsetInAppendMe >= appendMe.length) {
- return -1;
- }
- int allowedLen = Math.max(len, appendMe.length - offsetInAppendMe);
- System.arraycopy(appendMe, offsetInAppendMe, cbuf, off, allowedLen);
- return allowedLen;
+ return input.read(cbuf, off, len);
}
}
diff --git a/server/src/test/java/org/elasticsearch/indices/analyze/AnalyzeActionIT.java b/server/src/test/java/org/elasticsearch/indices/analyze/AnalyzeActionIT.java
index 802761780a7..9d0c512f785 100644
--- a/server/src/test/java/org/elasticsearch/indices/analyze/AnalyzeActionIT.java
+++ b/server/src/test/java/org/elasticsearch/indices/analyze/AnalyzeActionIT.java
@@ -22,11 +22,18 @@ import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse;
import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.index.analysis.CharFilterFactory;
+import org.elasticsearch.indices.analysis.AnalysisModule;
+import org.elasticsearch.plugins.AnalysisPlugin;
+import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase;
+import org.elasticsearch.test.MockKeywordPlugin;
import org.hamcrest.core.IsNull;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -38,6 +45,12 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
public class AnalyzeActionIT extends ESIntegTestCase {
+
+ @Override
+ protected Collection> nodePlugins() {
+ return Collections.singleton(MockKeywordPlugin.class);
+ }
+
public void testSimpleAnalyzerTests() throws Exception {
assertAcked(prepareCreate("test").addAlias(new Alias("alias")));
ensureGreen();
diff --git a/server/src/test/java/org/elasticsearch/script/ScriptMetaDataTests.java b/server/src/test/java/org/elasticsearch/script/ScriptMetaDataTests.java
index 32d4d48a448..bef20190acf 100644
--- a/server/src/test/java/org/elasticsearch/script/ScriptMetaDataTests.java
+++ b/server/src/test/java/org/elasticsearch/script/ScriptMetaDataTests.java
@@ -81,10 +81,12 @@ public class ScriptMetaDataTests extends AbstractSerializingTestCase> nodePlugins() {
- return Collections.singletonList(InternalSettingsPlugin.class);
+ return Arrays.asList(InternalSettingsPlugin.class, MockKeywordPlugin.class);
}
public void testHighlightingWithStoredKeyword() throws IOException {
diff --git a/server/src/test/java/org/elasticsearch/search/query/MultiMatchQueryIT.java b/server/src/test/java/org/elasticsearch/search/query/MultiMatchQueryIT.java
index c8d57b96856..926839f2af2 100644
--- a/server/src/test/java/org/elasticsearch/search/query/MultiMatchQueryIT.java
+++ b/server/src/test/java/org/elasticsearch/search/query/MultiMatchQueryIT.java
@@ -32,15 +32,19 @@ import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.search.MatchQuery;
+import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.ESIntegTestCase;
+import org.elasticsearch.test.MockKeywordPlugin;
import org.junit.Before;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
@@ -72,6 +76,11 @@ import static org.hamcrest.Matchers.lessThan;
public class MultiMatchQueryIT extends ESIntegTestCase {
+ @Override
+ protected Collection> nodePlugins() {
+ return Collections.singleton(MockKeywordPlugin.class);
+ }
+
@Before
public void init() throws Exception {
CreateIndexRequestBuilder builder = prepareCreate("test").setSettings(Settings.builder()
diff --git a/test/framework/src/main/java/org/elasticsearch/indices/analysis/AnalysisFactoryTestCase.java b/test/framework/src/main/java/org/elasticsearch/indices/analysis/AnalysisFactoryTestCase.java
index f26c44e05f5..c5b89adfd73 100644
--- a/test/framework/src/main/java/org/elasticsearch/indices/analysis/AnalysisFactoryTestCase.java
+++ b/test/framework/src/main/java/org/elasticsearch/indices/analysis/AnalysisFactoryTestCase.java
@@ -24,7 +24,6 @@ import org.apache.lucene.analysis.util.TokenFilterFactory;
import org.apache.lucene.analysis.util.TokenizerFactory;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.index.analysis.HunspellTokenFilterFactory;
-import org.elasticsearch.index.analysis.KeywordTokenizerFactory;
import org.elasticsearch.index.analysis.MultiTermAwareComponent;
import org.elasticsearch.index.analysis.PreConfiguredCharFilter;
import org.elasticsearch.index.analysis.PreConfiguredTokenFilter;
@@ -79,7 +78,7 @@ public abstract class AnalysisFactoryTestCase extends ESTestCase {
// exposed in ES
.put("classic", MovedToAnalysisCommon.class)
.put("edgengram", MovedToAnalysisCommon.class)
- .put("keyword", KeywordTokenizerFactory.class)
+ .put("keyword", MovedToAnalysisCommon.class)
.put("letter", MovedToAnalysisCommon.class)
.put("lowercase", MovedToAnalysisCommon.class)
.put("ngram", MovedToAnalysisCommon.class)
diff --git a/test/framework/src/main/java/org/elasticsearch/test/MockKeywordPlugin.java b/test/framework/src/main/java/org/elasticsearch/test/MockKeywordPlugin.java
new file mode 100644
index 00000000000..fb9da1dad40
--- /dev/null
+++ b/test/framework/src/main/java/org/elasticsearch/test/MockKeywordPlugin.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.test;
+
+import org.apache.lucene.analysis.MockTokenizer;
+import org.apache.lucene.analysis.Tokenizer;
+import org.elasticsearch.index.analysis.TokenizerFactory;
+import org.elasticsearch.indices.analysis.AnalysisModule;
+import org.elasticsearch.plugins.AnalysisPlugin;
+import org.elasticsearch.plugins.Plugin;
+
+import java.util.Map;
+
+import static java.util.Collections.singletonMap;
+
+/**
+ * Some tests rely on the keyword tokenizer, but this tokenizer isn't part of lucene-core and therefor not available
+ * in some modules. What this test plugin does, is use the mock tokenizer and advertise that as the keyword tokenizer.
+ *
+ * Most tests that need this test plugin use normalizers. When normalizers are constructed they try to resolve the
+ * keyword tokenizer, but if the keyword tokenizer isn't available then constructing normalizers will fail.
+ */
+public class MockKeywordPlugin extends Plugin implements AnalysisPlugin {
+
+ @Override
+ public Map> getTokenizers() {
+ return singletonMap("keyword", (indexSettings, environment, name, settings) -> {
+ class Factory implements TokenizerFactory {
+
+ @Override
+ public Tokenizer create() {
+ return new MockTokenizer(MockTokenizer.KEYWORD, false);
+ }
+ }
+ return new Factory();
+ });
+ }
+}
diff --git a/x-pack/plugin/core/build.gradle b/x-pack/plugin/core/build.gradle
index ca38aee302e..4bbe339a09b 100644
--- a/x-pack/plugin/core/build.gradle
+++ b/x-pack/plugin/core/build.gradle
@@ -88,6 +88,7 @@ compileTestJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes,-serial,-
licenseHeaders {
approvedLicenses << 'BCrypt (BSD-like)'
additionalLicense 'BCRYP', 'BCrypt (BSD-like)', 'Copyright (c) 2006 Damien Miller '
+ excludes << 'org/elasticsearch/xpack/core/ssl/DerParser.java'
}
// make LicenseSigner available for testing signed licenses
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackPlugin.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackPlugin.java
index 77d521e2d43..9568a36551c 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackPlugin.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackPlugin.java
@@ -7,7 +7,6 @@ package org.elasticsearch.xpack.core;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.util.SetOnce;
-import org.bouncycastle.operator.OperatorCreationException;
import org.elasticsearch.SpecialPermission;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequest;
@@ -125,7 +124,7 @@ public class XPackPlugin extends XPackClientPlugin implements ScriptPlugin, Exte
public XPackPlugin(
final Settings settings,
- final Path configPath) throws IOException, DestroyFailedException, OperatorCreationException, GeneralSecurityException {
+ final Path configPath) {
super(settings);
this.settings = settings;
this.transportClientMode = transportClientMode(settings);
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertGenUtils.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertGenUtils.java
new file mode 100644
index 00000000000..6273456aca2
--- /dev/null
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertGenUtils.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+package org.elasticsearch.xpack.core.ssl;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.DERUTF8String;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.ExtensionsGenerator;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.Time;
+import org.bouncycastle.cert.CertIOException;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.SuppressForbidden;
+import org.elasticsearch.common.network.InetAddressHelper;
+import org.elasticsearch.common.network.NetworkAddress;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+import javax.net.ssl.X509ExtendedKeyManager;
+import javax.net.ssl.X509ExtendedTrustManager;
+import javax.security.auth.x500.X500Principal;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Set;
+
+
+/**
+ * Utility methods that deal with {@link Certificate}, {@link KeyStore}, {@link X509ExtendedTrustManager}, {@link X509ExtendedKeyManager}
+ * and other certificate related objects.
+ */
+public class CertGenUtils {
+
+ private static final String CN_OID = "2.5.4.3";
+
+ private static final int SERIAL_BIT_LENGTH = 20 * 8;
+ private static final BouncyCastleProvider BC_PROV = new BouncyCastleProvider();
+
+ private CertGenUtils() {
+ }
+
+ /**
+ * Generates a CA certificate
+ */
+ public static X509Certificate generateCACertificate(X500Principal x500Principal, KeyPair keyPair, int days)
+ throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException {
+ return generateSignedCertificate(x500Principal, null, keyPair, null, null, true, days, null);
+ }
+
+ /**
+ * Generates a signed certificate using the provided CA private key and
+ * information from the CA certificate
+ *
+ * @param principal the principal of the certificate; commonly referred to as the
+ * distinguished name (DN)
+ * @param subjectAltNames the subject alternative names that should be added to the
+ * certificate as an X509v3 extension. May be {@code null}
+ * @param keyPair the key pair that will be associated with the certificate
+ * @param caCert the CA certificate. If {@code null}, this results in a self signed
+ * certificate
+ * @param caPrivKey the CA private key. If {@code null}, this results in a self signed
+ * certificate
+ * @param days no of days certificate will be valid from now
+ * @return a signed {@link X509Certificate}
+ */
+ public static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair,
+ X509Certificate caCert, PrivateKey caPrivKey, int days)
+ throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException {
+ return generateSignedCertificate(principal, subjectAltNames, keyPair, caCert, caPrivKey, false, days, null);
+ }
+
+ /**
+ * Generates a signed certificate using the provided CA private key and
+ * information from the CA certificate
+ *
+ * @param principal the principal of the certificate; commonly referred to as the
+ * distinguished name (DN)
+ * @param subjectAltNames the subject alternative names that should be added to the
+ * certificate as an X509v3 extension. May be {@code null}
+ * @param keyPair the key pair that will be associated with the certificate
+ * @param caCert the CA certificate. If {@code null}, this results in a self signed
+ * certificate
+ * @param caPrivKey the CA private key. If {@code null}, this results in a self signed
+ * certificate
+ * @param days no of days certificate will be valid from now
+ * @param signatureAlgorithm algorithm used for signing certificate. If {@code null} or
+ * empty, then use default algorithm {@link CertGenUtils#getDefaultSignatureAlgorithm(PrivateKey)}
+ * @return a signed {@link X509Certificate}
+ */
+ public static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair,
+ X509Certificate caCert, PrivateKey caPrivKey,
+ int days, String signatureAlgorithm)
+ throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException {
+ return generateSignedCertificate(principal, subjectAltNames, keyPair, caCert, caPrivKey, false, days, signatureAlgorithm);
+ }
+
+ /**
+ * Generates a signed certificate
+ *
+ * @param principal the principal of the certificate; commonly referred to as the
+ * distinguished name (DN)
+ * @param subjectAltNames the subject alternative names that should be added to the
+ * certificate as an X509v3 extension. May be {@code null}
+ * @param keyPair the key pair that will be associated with the certificate
+ * @param caCert the CA certificate. If {@code null}, this results in a self signed
+ * certificate
+ * @param caPrivKey the CA private key. If {@code null}, this results in a self signed
+ * certificate
+ * @param isCa whether or not the generated certificate is a CA
+ * @param days no of days certificate will be valid from now
+ * @param signatureAlgorithm algorithm used for signing certificate. If {@code null} or
+ * empty, then use default algorithm {@link CertGenUtils#getDefaultSignatureAlgorithm(PrivateKey)}
+ * @return a signed {@link X509Certificate}
+ */
+ private static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair,
+ X509Certificate caCert, PrivateKey caPrivKey, boolean isCa,
+ int days, String signatureAlgorithm)
+ throws NoSuchAlgorithmException, CertificateException, CertIOException, OperatorCreationException {
+ Objects.requireNonNull(keyPair, "Key-Pair must not be null");
+ final DateTime notBefore = new DateTime(DateTimeZone.UTC);
+ if (days < 1) {
+ throw new IllegalArgumentException("the certificate must be valid for at least one day");
+ }
+ final DateTime notAfter = notBefore.plusDays(days);
+ final BigInteger serial = CertGenUtils.getSerial();
+ JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
+
+ X500Name subject = X500Name.getInstance(principal.getEncoded());
+ final X500Name issuer;
+ final AuthorityKeyIdentifier authorityKeyIdentifier;
+ if (caCert != null) {
+ if (caCert.getBasicConstraints() < 0) {
+ throw new IllegalArgumentException("ca certificate is not a CA!");
+ }
+ issuer = X500Name.getInstance(caCert.getIssuerX500Principal().getEncoded());
+ authorityKeyIdentifier = extUtils.createAuthorityKeyIdentifier(caCert.getPublicKey());
+ } else {
+ issuer = subject;
+ authorityKeyIdentifier = extUtils.createAuthorityKeyIdentifier(keyPair.getPublic());
+ }
+
+ JcaX509v3CertificateBuilder builder =
+ new JcaX509v3CertificateBuilder(issuer, serial,
+ new Time(notBefore.toDate(), Locale.ROOT), new Time(notAfter.toDate(), Locale.ROOT), subject, keyPair.getPublic());
+
+ builder.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(keyPair.getPublic()));
+ builder.addExtension(Extension.authorityKeyIdentifier, false, authorityKeyIdentifier);
+ if (subjectAltNames != null) {
+ builder.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);
+ }
+ builder.addExtension(Extension.basicConstraints, isCa, new BasicConstraints(isCa));
+
+ PrivateKey signingKey = caPrivKey != null ? caPrivKey : keyPair.getPrivate();
+ ContentSigner signer = new JcaContentSignerBuilder(
+ (Strings.isNullOrEmpty(signatureAlgorithm)) ? getDefaultSignatureAlgorithm(signingKey) : signatureAlgorithm)
+ .setProvider(CertGenUtils.BC_PROV).build(signingKey);
+ X509CertificateHolder certificateHolder = builder.build(signer);
+ return new JcaX509CertificateConverter().getCertificate(certificateHolder);
+ }
+
+ /**
+ * Based on the private key algorithm {@link PrivateKey#getAlgorithm()}
+ * determines default signing algorithm used by CertGenUtils
+ *
+ * @param key {@link PrivateKey}
+ * @return algorithm
+ */
+ private static String getDefaultSignatureAlgorithm(PrivateKey key) {
+ String signatureAlgorithm = null;
+ switch (key.getAlgorithm()) {
+ case "RSA":
+ signatureAlgorithm = "SHA256withRSA";
+ break;
+ case "DSA":
+ signatureAlgorithm = "SHA256withDSA";
+ break;
+ case "EC":
+ signatureAlgorithm = "SHA256withECDSA";
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported algorithm : " + key.getAlgorithm()
+ + " for signature, allowed values for private key algorithm are [RSA, DSA, EC]");
+ }
+ return signatureAlgorithm;
+ }
+
+ /**
+ * Generates a certificate signing request
+ *
+ * @param keyPair the key pair that will be associated by the certificate generated from the certificate signing request
+ * @param principal the principal of the certificate; commonly referred to as the distinguished name (DN)
+ * @param sanList the subject alternative names that should be added to the certificate as an X509v3 extension. May be
+ * {@code null}
+ * @return a certificate signing request
+ */
+ static PKCS10CertificationRequest generateCSR(KeyPair keyPair, X500Principal principal, GeneralNames sanList)
+ throws IOException, OperatorCreationException {
+ Objects.requireNonNull(keyPair, "Key-Pair must not be null");
+ Objects.requireNonNull(keyPair.getPublic(), "Public-Key must not be null");
+ Objects.requireNonNull(principal, "Principal must not be null");
+ JcaPKCS10CertificationRequestBuilder builder = new JcaPKCS10CertificationRequestBuilder(principal, keyPair.getPublic());
+ if (sanList != null) {
+ ExtensionsGenerator extGen = new ExtensionsGenerator();
+ extGen.addExtension(Extension.subjectAlternativeName, false, sanList);
+ builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extGen.generate());
+ }
+
+ return builder.build(new JcaContentSignerBuilder("SHA256withRSA").setProvider(CertGenUtils.BC_PROV).build(keyPair.getPrivate()));
+ }
+
+ /**
+ * Gets a random serial for a certificate that is generated from a {@link SecureRandom}
+ */
+ public static BigInteger getSerial() {
+ SecureRandom random = new SecureRandom();
+ BigInteger serial = new BigInteger(SERIAL_BIT_LENGTH, random);
+ assert serial.compareTo(BigInteger.valueOf(0L)) >= 0;
+ return serial;
+ }
+
+ /**
+ * Generates a RSA key pair with the provided key size (in bits)
+ */
+ public static KeyPair generateKeyPair(int keysize) throws NoSuchAlgorithmException {
+ // generate a private key
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ keyPairGenerator.initialize(keysize);
+ return keyPairGenerator.generateKeyPair();
+ }
+
+ /**
+ * Converts the {@link InetAddress} objects into a {@link GeneralNames} object that is used to represent subject alternative names.
+ */
+ public static GeneralNames getSubjectAlternativeNames(boolean resolveName, Set addresses) throws SocketException {
+ Set generalNameList = new HashSet<>();
+ for (InetAddress address : addresses) {
+ if (address.isAnyLocalAddress()) {
+ // it is a wildcard address
+ for (InetAddress inetAddress : InetAddressHelper.getAllAddresses()) {
+ addSubjectAlternativeNames(resolveName, inetAddress, generalNameList);
+ }
+ } else {
+ addSubjectAlternativeNames(resolveName, address, generalNameList);
+ }
+ }
+ return new GeneralNames(generalNameList.toArray(new GeneralName[generalNameList.size()]));
+ }
+
+ @SuppressForbidden(reason = "need to use getHostName to resolve DNS name and getHostAddress to ensure we resolved the name")
+ private static void addSubjectAlternativeNames(boolean resolveName, InetAddress inetAddress, Set list) {
+ String hostaddress = inetAddress.getHostAddress();
+ String ip = NetworkAddress.format(inetAddress);
+ list.add(new GeneralName(GeneralName.iPAddress, ip));
+ if (resolveName && (inetAddress.isLinkLocalAddress() == false)) {
+ String possibleHostName = inetAddress.getHostName();
+ if (possibleHostName.equals(hostaddress) == false) {
+ list.add(new GeneralName(GeneralName.dNSName, possibleHostName));
+ }
+ }
+ }
+
+ /**
+ * Creates an X.509 {@link GeneralName} for use as a Common Name in the certificate's Subject Alternative Names
+ * extension. A common name is a name with a tag of {@link GeneralName#otherName OTHER}, with an object-id that references
+ * the {@link #CN_OID cn} attribute, an explicit tag of '0', and a DER encoded UTF8 string for the name.
+ * This usage of using the {@code cn} OID as a Subject Alternative Name is non-standard and will not be
+ * recognised by other X.509/TLS implementations.
+ */
+ public static GeneralName createCommonName(String cn) {
+ final ASN1Encodable[] sequence = {new ASN1ObjectIdentifier(CN_OID), new DERTaggedObject(true, 0, new DERUTF8String(cn))};
+ return new GeneralName(GeneralName.otherName, new DERSequence(sequence));
+ }
+}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertParsingUtils.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertParsingUtils.java
new file mode 100644
index 00000000000..8f66af14dfc
--- /dev/null
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertParsingUtils.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+package org.elasticsearch.xpack.core.ssl;
+
+import org.elasticsearch.common.Nullable;
+import org.elasticsearch.common.SuppressForbidden;
+import org.elasticsearch.common.io.PathUtils;
+import org.elasticsearch.common.settings.SecureString;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.env.Environment;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509ExtendedKeyManager;
+import javax.net.ssl.X509ExtendedTrustManager;
+import java.io.IOException;
+import java.io.InputStream;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings.getKeyStoreType;
+
+public class CertParsingUtils {
+
+ private CertParsingUtils() {
+ throw new IllegalStateException("Utility class should not be instantiated");
+ }
+ /**
+ * Resolves a path with or without an {@link Environment} as we may be running in a transport client where we do not have access to
+ * the environment
+ */
+ @SuppressForbidden(reason = "we don't have the environment to resolve files from when running in a transport client")
+ static Path resolvePath(String path, @Nullable Environment environment) {
+ if (environment != null) {
+ return environment.configFile().resolve(path);
+ }
+ return PathUtils.get(path).normalize();
+ }
+
+ static KeyStore readKeyStore(Path path, String type, char[] password)
+ throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
+ try (InputStream in = Files.newInputStream(path)) {
+ KeyStore store = KeyStore.getInstance(type);
+ assert password != null;
+ store.load(in, password);
+ return store;
+ }
+ }
+
+ /**
+ * Reads the provided paths and parses them into {@link Certificate} objects
+ *
+ * @param certPaths the paths to the PEM encoded certificates
+ * @param environment the environment to resolve files against. May be {@code null}
+ * @return an array of {@link Certificate} objects
+ */
+ public static Certificate[] readCertificates(List certPaths, @Nullable Environment environment)
+ throws CertificateException, IOException {
+ final List resolvedPaths = certPaths.stream().map(p -> resolvePath(p, environment)).collect(Collectors.toList());
+ return readCertificates(resolvedPaths);
+ }
+
+ public static Certificate[] readCertificates(List certPaths) throws CertificateException, IOException {
+ Collection certificates = new ArrayList<>();
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ for (Path path : certPaths) {
+ try (InputStream input = Files.newInputStream(path)) {
+ certificates.addAll((Collection) certFactory.generateCertificates(input));
+ }
+ }
+ return certificates.toArray(new Certificate[0]);
+ }
+
+ public static X509Certificate[] readX509Certificates(List certPaths) throws CertificateException, IOException {
+ Collection certificates = new ArrayList<>();
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ for (Path path : certPaths) {
+ try (InputStream input = Files.newInputStream(path)) {
+ certificates.addAll((Collection) certFactory.generateCertificates(input));
+ }
+ }
+ return certificates.toArray(new X509Certificate[0]);
+ }
+
+ static List readCertificates(InputStream input) throws CertificateException, IOException {
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ Collection certificates = (Collection) certFactory.generateCertificates(input);
+ return new ArrayList<>(certificates);
+ }
+
+ /**
+ * Read all certificate-key pairs from a PKCS#12 container.
+ *
+ * @param path The path to the PKCS#12 container file.
+ * @param password The password for the container file
+ * @param keyPassword A supplier for the password for each key. The key alias is supplied as an argument to the function, and it should
+ * return the password for that key. If it returns {@code null}, then the key-pair for that alias is not read.
+ */
+ public static Map readPkcs12KeyPairs(Path path, char[] password, Function keyPassword)
+ throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, UnrecoverableKeyException {
+ final KeyStore store = readKeyStore(path, "PKCS12", password);
+ final Enumeration enumeration = store.aliases();
+ final Map map = new HashMap<>(store.size());
+ while (enumeration.hasMoreElements()) {
+ final String alias = enumeration.nextElement();
+ if (store.isKeyEntry(alias)) {
+ final char[] pass = keyPassword.apply(alias);
+ map.put(store.getCertificate(alias), store.getKey(alias, pass));
+ }
+ }
+ return map;
+ }
+
+ /**
+ * Creates a {@link KeyStore} from a PEM encoded certificate and key file
+ */
+ static KeyStore getKeyStoreFromPEM(Path certificatePath, Path keyPath, char[] keyPassword)
+ throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException {
+ final PrivateKey key = PemUtils.readPrivateKey(keyPath, () -> keyPassword);
+ final Certificate[] certificates = readCertificates(Collections.singletonList(certificatePath));
+ return getKeyStore(certificates, key, keyPassword);
+ }
+
+ /**
+ * Returns a {@link X509ExtendedKeyManager} that is built from the provided private key and certificate chain
+ */
+ public static X509ExtendedKeyManager keyManager(Certificate[] certificateChain, PrivateKey privateKey, char[] password)
+ throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, IOException, CertificateException {
+ KeyStore keyStore = getKeyStore(certificateChain, privateKey, password);
+ return keyManager(keyStore, password, KeyManagerFactory.getDefaultAlgorithm());
+ }
+
+ private static KeyStore getKeyStore(Certificate[] certificateChain, PrivateKey privateKey, char[] password)
+ throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
+ KeyStore keyStore = KeyStore.getInstance("jks");
+ keyStore.load(null, null);
+ // password must be non-null for keystore...
+ keyStore.setKeyEntry("key", privateKey, password, certificateChain);
+ return keyStore;
+ }
+
+ /**
+ * Returns a {@link X509ExtendedKeyManager} that is built from the provided keystore
+ */
+ static X509ExtendedKeyManager keyManager(KeyStore keyStore, char[] password, String algorithm)
+ throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException {
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
+ kmf.init(keyStore, password);
+ KeyManager[] keyManagers = kmf.getKeyManagers();
+ for (KeyManager keyManager : keyManagers) {
+ if (keyManager instanceof X509ExtendedKeyManager) {
+ return (X509ExtendedKeyManager) keyManager;
+ }
+ }
+ throw new IllegalStateException("failed to find a X509ExtendedKeyManager");
+ }
+
+ public static X509ExtendedKeyManager getKeyManager(X509KeyPairSettings keyPair, Settings settings,
+ @Nullable String trustStoreAlgorithm, Environment environment) {
+ if (trustStoreAlgorithm == null) {
+ trustStoreAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ }
+ final KeyConfig keyConfig = createKeyConfig(keyPair, settings, trustStoreAlgorithm);
+ if (keyConfig == null) {
+ return null;
+ } else {
+ return keyConfig.createKeyManager(environment);
+ }
+ }
+
+ static KeyConfig createKeyConfig(X509KeyPairSettings keyPair, Settings settings, String trustStoreAlgorithm) {
+ String keyPath = keyPair.keyPath.get(settings).orElse(null);
+ String keyStorePath = keyPair.keystorePath.get(settings).orElse(null);
+
+ if (keyPath != null && keyStorePath != null) {
+ throw new IllegalArgumentException("you cannot specify a keystore and key file");
+ }
+
+ if (keyPath != null) {
+ SecureString keyPassword = keyPair.keyPassword.get(settings);
+ String certPath = keyPair.certificatePath.get(settings).orElse(null);
+ if (certPath == null) {
+ throw new IllegalArgumentException("you must specify the certificates [" + keyPair.certificatePath.getKey()
+ + "] to use with the key [" + keyPair.keyPath.getKey() + "]");
+ }
+ return new PEMKeyConfig(keyPath, keyPassword, certPath);
+ }
+
+ if (keyStorePath != null) {
+ SecureString keyStorePassword = keyPair.keystorePassword.get(settings);
+ String keyStoreAlgorithm = keyPair.keystoreAlgorithm.get(settings);
+ String keyStoreType = getKeyStoreType(keyPair.keystoreType, settings, keyStorePath);
+ SecureString keyStoreKeyPassword = keyPair.keystoreKeyPassword.get(settings);
+ if (keyStoreKeyPassword.length() == 0) {
+ keyStoreKeyPassword = keyStorePassword;
+ }
+ return new StoreKeyConfig(keyStorePath, keyStoreType, keyStorePassword, keyStoreKeyPassword, keyStoreAlgorithm,
+ trustStoreAlgorithm);
+ }
+ return null;
+
+ }
+
+ /**
+ * Creates a {@link X509ExtendedTrustManager} based on the provided certificates
+ *
+ * @param certificates the certificates to trust
+ * @return a trust manager that trusts the provided certificates
+ */
+ public static X509ExtendedTrustManager trustManager(Certificate[] certificates)
+ throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
+ KeyStore store = trustStore(certificates);
+ return trustManager(store, TrustManagerFactory.getDefaultAlgorithm());
+ }
+
+ static KeyStore trustStore(Certificate[] certificates)
+ throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
+ assert certificates != null : "Cannot create trust store with null certificates";
+ KeyStore store = KeyStore.getInstance("jks");
+ store.load(null, null);
+ int counter = 0;
+ for (Certificate certificate : certificates) {
+ store.setCertificateEntry("cert" + counter, certificate);
+ counter++;
+ }
+ return store;
+ }
+
+ /**
+ * Loads the truststore and creates a {@link X509ExtendedTrustManager}
+ *
+ * @param trustStorePath the path to the truststore
+ * @param trustStorePassword the password to the truststore
+ * @param trustStoreAlgorithm the algorithm to use for the truststore
+ * @param env the environment to use for file resolution. May be {@code null}
+ * @return a trust manager with the trust material from the store
+ */
+ public static X509ExtendedTrustManager trustManager(String trustStorePath, String trustStoreType, char[] trustStorePassword,
+ String trustStoreAlgorithm, @Nullable Environment env)
+ throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
+ KeyStore trustStore = readKeyStore(resolvePath(trustStorePath, env), trustStoreType, trustStorePassword);
+ return trustManager(trustStore, trustStoreAlgorithm);
+ }
+
+ /**
+ * Creates a {@link X509ExtendedTrustManager} based on the trust material in the provided {@link KeyStore}
+ */
+ static X509ExtendedTrustManager trustManager(KeyStore keyStore, String algorithm)
+ throws NoSuchAlgorithmException, KeyStoreException {
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
+ tmf.init(keyStore);
+ TrustManager[] trustManagers = tmf.getTrustManagers();
+ for (TrustManager trustManager : trustManagers) {
+ if (trustManager instanceof X509ExtendedTrustManager) {
+ return (X509ExtendedTrustManager) trustManager;
+ }
+ }
+ throw new IllegalStateException("failed to find a X509ExtendedTrustManager");
+ }
+}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertUtils.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertUtils.java
deleted file mode 100644
index 557ef3f1de7..00000000000
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertUtils.java
+++ /dev/null
@@ -1,667 +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;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.core.ssl;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
-import org.bouncycastle.asn1.x509.BasicConstraints;
-import org.bouncycastle.asn1.x509.Extension;
-import org.bouncycastle.asn1.x509.ExtensionsGenerator;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.Time;
-import org.bouncycastle.cert.CertIOException;
-import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
-import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
-import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.openssl.PEMEncryptedKeyPair;
-import org.bouncycastle.openssl.PEMKeyPair;
-import org.bouncycastle.openssl.PEMParser;
-import org.bouncycastle.openssl.X509TrustedCertificateBlock;
-import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
-import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
-import org.bouncycastle.pkcs.PKCS10CertificationRequest;
-import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
-import org.elasticsearch.common.Nullable;
-import org.elasticsearch.common.Strings;
-import org.elasticsearch.common.SuppressForbidden;
-import org.elasticsearch.common.io.PathUtils;
-import org.elasticsearch.common.network.InetAddressHelper;
-import org.elasticsearch.common.network.NetworkAddress;
-import org.elasticsearch.common.settings.SecureString;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.env.Environment;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509ExtendedKeyManager;
-import javax.net.ssl.X509ExtendedTrustManager;
-import javax.security.auth.x500.X500Principal;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.SocketException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.security.Key;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-
-import static org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings.getKeyStoreType;
-
-/**
- * Utility methods that deal with {@link Certificate}, {@link KeyStore}, {@link X509ExtendedTrustManager}, {@link X509ExtendedKeyManager}
- * and other certificate related objects.
- */
-public class CertUtils {
-
- static final String CN_OID = "2.5.4.3";
-
- private static final int SERIAL_BIT_LENGTH = 20 * 8;
- static final BouncyCastleProvider BC_PROV = new BouncyCastleProvider();
-
- private CertUtils() {
- }
-
- /**
- * Resolves a path with or without an {@link Environment} as we may be running in a transport client where we do not have access to
- * the environment
- */
- @SuppressForbidden(reason = "we don't have the environment to resolve files from when running in a transport client")
- static Path resolvePath(String path, @Nullable Environment environment) {
- if (environment != null) {
- return environment.configFile().resolve(path);
- }
- return PathUtils.get(path).normalize();
- }
-
- /**
- * Creates a {@link KeyStore} from a PEM encoded certificate and key file
- */
- static KeyStore getKeyStoreFromPEM(Path certificatePath, Path keyPath, char[] keyPassword)
- throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException {
- final PrivateKey key;
- try (Reader reader = Files.newBufferedReader(keyPath, StandardCharsets.UTF_8)) {
- key = CertUtils.readPrivateKey(reader, () -> keyPassword);
- }
- final Certificate[] certificates = readCertificates(Collections.singletonList(certificatePath));
- return getKeyStore(certificates, key, keyPassword);
- }
-
-
- /**
- * Returns a {@link X509ExtendedKeyManager} that is built from the provided private key and certificate chain
- */
- public static X509ExtendedKeyManager keyManager(Certificate[] certificateChain, PrivateKey privateKey, char[] password)
- throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, IOException, CertificateException {
- KeyStore keyStore = getKeyStore(certificateChain, privateKey, password);
- return keyManager(keyStore, password, KeyManagerFactory.getDefaultAlgorithm());
- }
-
- private static KeyStore getKeyStore(Certificate[] certificateChain, PrivateKey privateKey, char[] password)
- throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
- KeyStore keyStore = KeyStore.getInstance("jks");
- keyStore.load(null, null);
- // password must be non-null for keystore...
- keyStore.setKeyEntry("key", privateKey, password, certificateChain);
- return keyStore;
- }
-
- /**
- * Returns a {@link X509ExtendedKeyManager} that is built from the provided keystore
- */
- static X509ExtendedKeyManager keyManager(KeyStore keyStore, char[] password, String algorithm)
- throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException {
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
- kmf.init(keyStore, password);
- KeyManager[] keyManagers = kmf.getKeyManagers();
- for (KeyManager keyManager : keyManagers) {
- if (keyManager instanceof X509ExtendedKeyManager) {
- return (X509ExtendedKeyManager) keyManager;
- }
- }
- throw new IllegalStateException("failed to find a X509ExtendedKeyManager");
- }
-
- public static X509ExtendedKeyManager getKeyManager(X509KeyPairSettings keyPair, Settings settings,
- @Nullable String trustStoreAlgorithm, Environment environment) {
- if (trustStoreAlgorithm == null) {
- trustStoreAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
- }
- final KeyConfig keyConfig = createKeyConfig(keyPair, settings, trustStoreAlgorithm);
- if (keyConfig == null) {
- return null;
- } else {
- return keyConfig.createKeyManager(environment);
- }
- }
-
- static KeyConfig createKeyConfig(X509KeyPairSettings keyPair, Settings settings, String trustStoreAlgorithm) {
- String keyPath = keyPair.keyPath.get(settings).orElse(null);
- String keyStorePath = keyPair.keystorePath.get(settings).orElse(null);
-
- if (keyPath != null && keyStorePath != null) {
- throw new IllegalArgumentException("you cannot specify a keystore and key file");
- }
-
- if (keyPath != null) {
- SecureString keyPassword = keyPair.keyPassword.get(settings);
- String certPath = keyPair.certificatePath.get(settings).orElse(null);
- if (certPath == null) {
- throw new IllegalArgumentException("you must specify the certificates [" + keyPair.certificatePath.getKey()
- + "] to use with the key [" + keyPair.keyPath.getKey() + "]");
- }
- return new PEMKeyConfig(keyPath, keyPassword, certPath);
- }
-
- if (keyStorePath != null) {
- SecureString keyStorePassword = keyPair.keystorePassword.get(settings);
- String keyStoreAlgorithm = keyPair.keystoreAlgorithm.get(settings);
- String keyStoreType = getKeyStoreType(keyPair.keystoreType, settings, keyStorePath);
- SecureString keyStoreKeyPassword = keyPair.keystoreKeyPassword.get(settings);
- if (keyStoreKeyPassword.length() == 0) {
- keyStoreKeyPassword = keyStorePassword;
- }
- return new StoreKeyConfig(keyStorePath, keyStoreType, keyStorePassword, keyStoreKeyPassword, keyStoreAlgorithm,
- trustStoreAlgorithm);
- }
- return null;
-
- }
-
- /**
- * Creates a {@link X509ExtendedTrustManager} based on the provided certificates
- *
- * @param certificates the certificates to trust
- * @return a trust manager that trusts the provided certificates
- */
- public static X509ExtendedTrustManager trustManager(Certificate[] certificates)
- throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, IOException, CertificateException {
- KeyStore store = trustStore(certificates);
- return trustManager(store, TrustManagerFactory.getDefaultAlgorithm());
- }
-
- static KeyStore trustStore(Certificate[] certificates)
- throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
- assert certificates != null : "Cannot create trust store with null certificates";
- KeyStore store = KeyStore.getInstance("jks");
- store.load(null, null);
- int counter = 0;
- for (Certificate certificate : certificates) {
- store.setCertificateEntry("cert" + counter, certificate);
- counter++;
- }
- return store;
- }
-
- /**
- * Loads the truststore and creates a {@link X509ExtendedTrustManager}
- *
- * @param trustStorePath the path to the truststore
- * @param trustStorePassword the password to the truststore
- * @param trustStoreAlgorithm the algorithm to use for the truststore
- * @param env the environment to use for file resolution. May be {@code null}
- * @return a trust manager with the trust material from the store
- */
- public static X509ExtendedTrustManager trustManager(String trustStorePath, String trustStoreType, char[] trustStorePassword,
- String trustStoreAlgorithm, @Nullable Environment env)
- throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, IOException, CertificateException {
- KeyStore trustStore = readKeyStore(resolvePath(trustStorePath, env), trustStoreType, trustStorePassword);
- return trustManager(trustStore, trustStoreAlgorithm);
- }
-
- static KeyStore readKeyStore(Path path, String type, char[] password)
- throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
- try (InputStream in = Files.newInputStream(path)) {
- KeyStore store = KeyStore.getInstance(type);
- assert password != null;
- store.load(in, password);
- return store;
- }
- }
-
- /**
- * Creates a {@link X509ExtendedTrustManager} based on the trust material in the provided {@link KeyStore}
- */
- static X509ExtendedTrustManager trustManager(KeyStore keyStore, String algorithm)
- throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, IOException, CertificateException {
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
- tmf.init(keyStore);
- TrustManager[] trustManagers = tmf.getTrustManagers();
- for (TrustManager trustManager : trustManagers) {
- if (trustManager instanceof X509ExtendedTrustManager) {
- return (X509ExtendedTrustManager) trustManager;
- }
- }
- throw new IllegalStateException("failed to find a X509ExtendedTrustManager");
- }
-
- /**
- * Reads the provided paths and parses them into {@link Certificate} objects
- *
- * @param certPaths the paths to the PEM encoded certificates
- * @param environment the environment to resolve files against. May be {@code null}
- * @return an array of {@link Certificate} objects
- */
- public static Certificate[] readCertificates(List certPaths, @Nullable Environment environment)
- throws CertificateException, IOException {
- final List resolvedPaths = certPaths.stream().map(p -> resolvePath(p, environment)).collect(Collectors.toList());
- return readCertificates(resolvedPaths);
- }
-
- public static Certificate[] readCertificates(List certPaths) throws CertificateException, IOException {
- List certificates = new ArrayList<>(certPaths.size());
- CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
- for (Path path : certPaths) {
- try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
- readCertificates(reader, certificates, certFactory);
- }
- }
- return certificates.toArray(new Certificate[certificates.size()]);
- }
-
- /**
- * Reads the certificates from the provided reader
- */
- static void readCertificates(Reader reader, List certificates, CertificateFactory certFactory)
- throws IOException, CertificateException {
- try (PEMParser pemParser = new PEMParser(reader)) {
-
- Object parsed = pemParser.readObject();
- if (parsed == null) {
- throw new IllegalArgumentException("could not parse pem certificate");
- }
-
- while (parsed != null) {
- X509CertificateHolder holder;
- if (parsed instanceof X509CertificateHolder) {
- holder = (X509CertificateHolder) parsed;
- } else if (parsed instanceof X509TrustedCertificateBlock) {
- X509TrustedCertificateBlock certificateBlock = (X509TrustedCertificateBlock) parsed;
- holder = certificateBlock.getCertificateHolder();
- } else {
- String msg = "parsed an unsupported object [" + parsed.getClass().getSimpleName() + "]";
- if (parsed instanceof PEMEncryptedKeyPair || parsed instanceof PEMKeyPair || parsed instanceof PrivateKeyInfo) {
- msg = msg + ". Encountered a PEM Key while expecting a PEM certificate.";
- }
- throw new IllegalArgumentException(msg);
- }
- certificates.add(certFactory.generateCertificate(new ByteArrayInputStream(holder.getEncoded())));
- parsed = pemParser.readObject();
- }
- }
- }
-
- /**
- * Reads the private key from the reader and optionally uses the password supplier to retrieve a password if the key is encrypted
- */
- public static PrivateKey readPrivateKey(Reader reader, Supplier passwordSupplier) throws IOException {
- try (PEMParser parser = new PEMParser(reader)) {
- PrivateKeyInfo privateKeyInfo = innerReadPrivateKey(parser, passwordSupplier);
- if (parser.readObject() != null) {
- throw new IllegalStateException("key file contained more that one entry");
- }
- JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
- converter.setProvider(BC_PROV);
- return converter.getPrivateKey(privateKeyInfo);
- }
- }
-
- private static PrivateKeyInfo innerReadPrivateKey(PEMParser parser, Supplier passwordSupplier) throws IOException {
- final Object parsed = parser.readObject();
- if (parsed == null) {
- throw new IllegalStateException("key file did not contain a supported key");
- }
-
- PrivateKeyInfo privateKeyInfo;
- if (parsed instanceof PEMEncryptedKeyPair) {
- char[] keyPassword = passwordSupplier.get();
- if (keyPassword == null) {
- throw new IllegalArgumentException("cannot read encrypted key without a password");
- }
- // we have an encrypted key pair so we need to decrypt it
- PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair) parsed;
- privateKeyInfo = encryptedKeyPair
- .decryptKeyPair(new JcePEMDecryptorProviderBuilder().setProvider(BC_PROV).build(keyPassword))
- .getPrivateKeyInfo();
- } else if (parsed instanceof PEMKeyPair) {
- privateKeyInfo = ((PEMKeyPair) parsed).getPrivateKeyInfo();
- } else if (parsed instanceof PrivateKeyInfo) {
- privateKeyInfo = (PrivateKeyInfo) parsed;
- } else if (parsed instanceof ASN1ObjectIdentifier) {
- // skip this object and recurse into this method again to read the next object
- return innerReadPrivateKey(parser, passwordSupplier);
- } else {
- String msg = "parsed an unsupported object [" + parsed.getClass().getSimpleName() + "]";
- if (parsed instanceof X509CertificateHolder || parsed instanceof X509TrustedCertificateBlock) {
- msg = msg + ". Encountered a PEM Certificate while expecting a PEM Key.";
- }
- throw new IllegalArgumentException(msg);
- }
-
- return privateKeyInfo;
- }
-
- /**
- * Read all certificate-key pairs from a PKCS#12 container.
- *
- * @param path The path to the PKCS#12 container file.
- * @param password The password for the container file
- * @param keyPassword A supplier for the password for each key. The key alias is supplied as an argument to the function, and it should
- * return the password for that key. If it returns {@code null}, then the key-pair for that alias is not read.
- */
- public static Map readPkcs12KeyPairs(Path path, char[] password, Function keyPassword, Environment
- env)
- throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, UnrecoverableKeyException {
- final KeyStore store = readKeyStore(path, "PKCS12", password);
- final Enumeration enumeration = store.aliases();
- final Map map = new HashMap<>(store.size());
- while (enumeration.hasMoreElements()) {
- final String alias = enumeration.nextElement();
- if (store.isKeyEntry(alias)) {
- final char[] pass = keyPassword.apply(alias);
- map.put(store.getCertificate(alias), store.getKey(alias, pass));
- }
- }
- return map;
- }
-
- /**
- * Generates a CA certificate
- */
- public static X509Certificate generateCACertificate(X500Principal x500Principal, KeyPair keyPair, int days)
- throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException {
- return generateSignedCertificate(x500Principal, null, keyPair, null, null, true, days, null);
- }
-
- /**
- * Generates a signed certificate using the provided CA private key and
- * information from the CA certificate
- *
- * @param principal
- * the principal of the certificate; commonly referred to as the
- * distinguished name (DN)
- * @param subjectAltNames
- * the subject alternative names that should be added to the
- * certificate as an X509v3 extension. May be {@code null}
- * @param keyPair
- * the key pair that will be associated with the certificate
- * @param caCert
- * the CA certificate. If {@code null}, this results in a self signed
- * certificate
- * @param caPrivKey
- * the CA private key. If {@code null}, this results in a self signed
- * certificate
- * @param days
- * no of days certificate will be valid from now
- * @return a signed {@link X509Certificate}
- */
- public static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair,
- X509Certificate caCert, PrivateKey caPrivKey, int days)
- throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException {
- return generateSignedCertificate(principal, subjectAltNames, keyPair, caCert, caPrivKey, false, days, null);
- }
-
- /**
- * Generates a signed certificate using the provided CA private key and
- * information from the CA certificate
- *
- * @param principal
- * the principal of the certificate; commonly referred to as the
- * distinguished name (DN)
- * @param subjectAltNames
- * the subject alternative names that should be added to the
- * certificate as an X509v3 extension. May be {@code null}
- * @param keyPair
- * the key pair that will be associated with the certificate
- * @param caCert
- * the CA certificate. If {@code null}, this results in a self signed
- * certificate
- * @param caPrivKey
- * the CA private key. If {@code null}, this results in a self signed
- * certificate
- * @param days
- * no of days certificate will be valid from now
- * @param signatureAlgorithm
- * algorithm used for signing certificate. If {@code null} or
- * empty, then use default algorithm {@link CertUtils#getDefaultSignatureAlgorithm(PrivateKey)}
- * @return a signed {@link X509Certificate}
- */
- public static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair,
- X509Certificate caCert, PrivateKey caPrivKey, int days, String signatureAlgorithm)
- throws OperatorCreationException, CertificateException, CertIOException, NoSuchAlgorithmException {
- return generateSignedCertificate(principal, subjectAltNames, keyPair, caCert, caPrivKey, false, days, signatureAlgorithm);
- }
-
- /**
- * Generates a signed certificate
- *
- * @param principal
- * the principal of the certificate; commonly referred to as the
- * distinguished name (DN)
- * @param subjectAltNames
- * the subject alternative names that should be added to the
- * certificate as an X509v3 extension. May be {@code null}
- * @param keyPair
- * the key pair that will be associated with the certificate
- * @param caCert
- * the CA certificate. If {@code null}, this results in a self signed
- * certificate
- * @param caPrivKey
- * the CA private key. If {@code null}, this results in a self signed
- * certificate
- * @param isCa
- * whether or not the generated certificate is a CA
- * @param days
- * no of days certificate will be valid from now
- * @param signatureAlgorithm
- * algorithm used for signing certificate. If {@code null} or
- * empty, then use default algorithm {@link CertUtils#getDefaultSignatureAlgorithm(PrivateKey)}
- * @return a signed {@link X509Certificate}
- */
- private static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair,
- X509Certificate caCert, PrivateKey caPrivKey, boolean isCa, int days, String signatureAlgorithm)
- throws NoSuchAlgorithmException, CertificateException, CertIOException, OperatorCreationException {
- Objects.requireNonNull(keyPair, "Key-Pair must not be null");
- final DateTime notBefore = new DateTime(DateTimeZone.UTC);
- if (days < 1) {
- throw new IllegalArgumentException("the certificate must be valid for at least one day");
- }
- final DateTime notAfter = notBefore.plusDays(days);
- final BigInteger serial = CertUtils.getSerial();
- JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
-
- X500Name subject = X500Name.getInstance(principal.getEncoded());
- final X500Name issuer;
- final AuthorityKeyIdentifier authorityKeyIdentifier;
- if (caCert != null) {
- if (caCert.getBasicConstraints() < 0) {
- throw new IllegalArgumentException("ca certificate is not a CA!");
- }
- issuer = X500Name.getInstance(caCert.getIssuerX500Principal().getEncoded());
- authorityKeyIdentifier = extUtils.createAuthorityKeyIdentifier(caCert.getPublicKey());
- } else {
- issuer = subject;
- authorityKeyIdentifier = extUtils.createAuthorityKeyIdentifier(keyPair.getPublic());
- }
-
- JcaX509v3CertificateBuilder builder =
- new JcaX509v3CertificateBuilder(issuer, serial,
- new Time(notBefore.toDate(), Locale.ROOT), new Time(notAfter.toDate(), Locale.ROOT), subject, keyPair.getPublic());
-
- builder.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(keyPair.getPublic()));
- builder.addExtension(Extension.authorityKeyIdentifier, false, authorityKeyIdentifier);
- if (subjectAltNames != null) {
- builder.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);
- }
- builder.addExtension(Extension.basicConstraints, isCa, new BasicConstraints(isCa));
-
- PrivateKey signingKey = caPrivKey != null ? caPrivKey : keyPair.getPrivate();
- ContentSigner signer = new JcaContentSignerBuilder(
- (Strings.isNullOrEmpty(signatureAlgorithm)) ? getDefaultSignatureAlgorithm(signingKey) : signatureAlgorithm)
- .setProvider(CertUtils.BC_PROV).build(signingKey);
- X509CertificateHolder certificateHolder = builder.build(signer);
- return new JcaX509CertificateConverter().getCertificate(certificateHolder);
- }
-
- /**
- * Based on the private key algorithm {@link PrivateKey#getAlgorithm()}
- * determines default signing algorithm used by CertUtils
- *
- * @param key
- * {@link PrivateKey}
- * @return algorithm
- */
- private static String getDefaultSignatureAlgorithm(PrivateKey key) {
- String signatureAlgorithm = null;
- switch (key.getAlgorithm()) {
- case "RSA":
- signatureAlgorithm = "SHA256withRSA";
- break;
- case "DSA":
- signatureAlgorithm = "SHA256withDSA";
- break;
- case "EC":
- signatureAlgorithm = "SHA256withECDSA";
- break;
- default:
- throw new IllegalArgumentException("Unsupported algorithm : " + key.getAlgorithm()
- + " for signature, allowed values for private key algorithm are [RSA, DSA, EC]");
- }
- return signatureAlgorithm;
- }
-
- /**
- * Generates a certificate signing request
- *
- * @param keyPair the key pair that will be associated by the certificate generated from the certificate signing request
- * @param principal the principal of the certificate; commonly referred to as the distinguished name (DN)
- * @param sanList the subject alternative names that should be added to the certificate as an X509v3 extension. May be
- * {@code null}
- * @return a certificate signing request
- */
- static PKCS10CertificationRequest generateCSR(KeyPair keyPair, X500Principal principal, GeneralNames sanList)
- throws IOException, OperatorCreationException {
- Objects.requireNonNull(keyPair, "Key-Pair must not be null");
- Objects.requireNonNull(keyPair.getPublic(), "Public-Key must not be null");
- Objects.requireNonNull(principal, "Principal must not be null");
- JcaPKCS10CertificationRequestBuilder builder = new JcaPKCS10CertificationRequestBuilder(principal, keyPair.getPublic());
- if (sanList != null) {
- ExtensionsGenerator extGen = new ExtensionsGenerator();
- extGen.addExtension(Extension.subjectAlternativeName, false, sanList);
- builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extGen.generate());
- }
-
- return builder.build(new JcaContentSignerBuilder("SHA256withRSA").setProvider(CertUtils.BC_PROV).build(keyPair.getPrivate()));
- }
-
- /**
- * Gets a random serial for a certificate that is generated from a {@link SecureRandom}
- */
- public static BigInteger getSerial() {
- SecureRandom random = new SecureRandom();
- BigInteger serial = new BigInteger(SERIAL_BIT_LENGTH, random);
- assert serial.compareTo(BigInteger.valueOf(0L)) >= 0;
- return serial;
- }
-
- /**
- * Generates a RSA key pair with the provided key size (in bits)
- */
- public static KeyPair generateKeyPair(int keysize) throws NoSuchAlgorithmException {
- // generate a private key
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
- keyPairGenerator.initialize(keysize);
- return keyPairGenerator.generateKeyPair();
- }
-
- /**
- * Converts the {@link InetAddress} objects into a {@link GeneralNames} object that is used to represent subject alternative names.
- */
- public static GeneralNames getSubjectAlternativeNames(boolean resolveName, Set addresses) throws SocketException {
- Set generalNameList = new HashSet<>();
- for (InetAddress address : addresses) {
- if (address.isAnyLocalAddress()) {
- // it is a wildcard address
- for (InetAddress inetAddress : InetAddressHelper.getAllAddresses()) {
- addSubjectAlternativeNames(resolveName, inetAddress, generalNameList);
- }
- } else {
- addSubjectAlternativeNames(resolveName, address, generalNameList);
- }
- }
- return new GeneralNames(generalNameList.toArray(new GeneralName[generalNameList.size()]));
- }
-
- @SuppressForbidden(reason = "need to use getHostName to resolve DNS name and getHostAddress to ensure we resolved the name")
- private static void addSubjectAlternativeNames(boolean resolveName, InetAddress inetAddress, Set list) {
- String hostaddress = inetAddress.getHostAddress();
- String ip = NetworkAddress.format(inetAddress);
- list.add(new GeneralName(GeneralName.iPAddress, ip));
- if (resolveName && (inetAddress.isLinkLocalAddress() == false)) {
- String possibleHostName = inetAddress.getHostName();
- if (possibleHostName.equals(hostaddress) == false) {
- list.add(new GeneralName(GeneralName.dNSName, possibleHostName));
- }
- }
- }
-
- /**
- * Creates an X.509 {@link GeneralName} for use as a Common Name in the certificate's Subject Alternative Names
- * extension. A common name is a name with a tag of {@link GeneralName#otherName OTHER}, with an object-id that references
- * the {@link #CN_OID cn} attribute, an explicit tag of '0', and a DER encoded UTF8 string for the name.
- * This usage of using the {@code cn} OID as a Subject Alternative Name is non-standard and will not be
- * recognised by other X.509/TLS implementations.
- */
- public static GeneralName createCommonName(String cn) {
- final ASN1Encodable[] sequence = { new ASN1ObjectIdentifier(CN_OID), new DERTaggedObject(true, 0, new DERUTF8String(cn)) };
- return new GeneralName(GeneralName.otherName, new DERSequence(sequence));
- }
-}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateTool.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateTool.java
index eb3a92ce5e8..5515978c3ca 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateTool.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateTool.java
@@ -11,6 +11,7 @@ import joptsimple.OptionSpec;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMEncryptor;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder;
@@ -82,6 +83,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
private static final Pattern ALLOWED_FILENAME_CHAR_PATTERN =
Pattern.compile("[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1," + MAX_FILENAME_LENGTH + "}");
private static final int DEFAULT_KEY_SIZE = 2048;
+ private static final BouncyCastleProvider BC_PROV = new BouncyCastleProvider();
/**
* Wraps the certgen object parser.
@@ -316,10 +318,10 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
static void generateAndWriteCsrs(Path outputFile, Collection certInfo, int keysize) throws Exception {
fullyWriteFile(outputFile, (outputStream, pemWriter) -> {
for (CertificateInformation certificateInformation : certInfo) {
- KeyPair keyPair = CertUtils.generateKeyPair(keysize);
+ KeyPair keyPair = CertGenUtils.generateKeyPair(keysize);
GeneralNames sanList = getSubjectAlternativeNamesValue(certificateInformation.ipAddresses, certificateInformation.dnsNames,
certificateInformation.commonNames);
- PKCS10CertificationRequest csr = CertUtils.generateCSR(keyPair, certificateInformation.name.x500Principal, sanList);
+ PKCS10CertificationRequest csr = CertGenUtils.generateCSR(keyPair, certificateInformation.name.x500Principal, sanList);
final String dirName = certificateInformation.name.filename + "/";
ZipEntry zipEntry = new ZipEntry(dirName);
@@ -361,7 +363,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
if (caCertPath != null) {
assert caKeyPath != null;
final String resolvedCaCertPath = resolvePath(caCertPath).toAbsolutePath().toString();
- Certificate[] certificates = CertUtils.readCertificates(Collections.singletonList(resolvedCaCertPath), env);
+ Certificate[] certificates = CertParsingUtils.readCertificates(Collections.singletonList(resolvedCaCertPath), env);
if (certificates.length != 1) {
throw new IllegalArgumentException("expected a single certificate in file [" + caCertPath + "] but found [" +
certificates.length + "]");
@@ -373,8 +375,8 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
// generate the CA keys and cert
X500Principal x500Principal = new X500Principal(dn);
- KeyPair keyPair = CertUtils.generateKeyPair(keysize);
- Certificate caCert = CertUtils.generateCACertificate(x500Principal, keyPair, days);
+ KeyPair keyPair = CertGenUtils.generateKeyPair(keysize);
+ Certificate caCert = CertGenUtils.generateCACertificate(x500Principal, keyPair, days);
final char[] password;
if (prompt) {
password = terminal.readSecret("Enter password for CA private key: ");
@@ -399,8 +401,8 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
writeCAInfoIfGenerated(outputStream, pemWriter, caInfo);
for (CertificateInformation certificateInformation : certificateInformations) {
- KeyPair keyPair = CertUtils.generateKeyPair(keysize);
- Certificate certificate = CertUtils.generateSignedCertificate(certificateInformation.name.x500Principal,
+ KeyPair keyPair = CertGenUtils.generateKeyPair(keysize);
+ Certificate certificate = CertGenUtils.generateSignedCertificate(certificateInformation.name.x500Principal,
getSubjectAlternativeNamesValue(certificateInformation.ipAddresses, certificateInformation.dnsNames,
certificateInformation.commonNames),
keyPair, caInfo.caCert, caInfo.privateKey, days);
@@ -483,7 +485,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
outputStream.putNextEntry(new ZipEntry(caDirName + "ca.key"));
if (info.password != null && info.password.length > 0) {
try {
- PEMEncryptor encryptor = new JcePEMEncryptorBuilder("DES-EDE3-CBC").setProvider(CertUtils.BC_PROV).build(info.password);
+ PEMEncryptor encryptor = new JcePEMEncryptorBuilder("DES-EDE3-CBC").setProvider(BC_PROV).build(info.password);
pemWriter.writeObject(info.privateKey, encryptor);
} finally {
// we can safely nuke the password chars now
@@ -584,8 +586,8 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
private static PrivateKey readPrivateKey(String path, char[] password, Terminal terminal, boolean prompt)
throws Exception {
AtomicReference passwordReference = new AtomicReference<>(password);
- try (Reader reader = Files.newBufferedReader(resolvePath(path), StandardCharsets.UTF_8)) {
- return CertUtils.readPrivateKey(reader, () -> {
+ try {
+ return PemUtils.readPrivateKey(resolvePath(path), () -> {
if (password != null || prompt == false) {
return password;
}
@@ -611,7 +613,7 @@ public class CertificateGenerateTool extends EnvironmentAwareCommand {
}
for (String cn : commonNames) {
- generalNameList.add(CertUtils.createCommonName(cn));
+ generalNameList.add(CertGenUtils.createCommonName(cn));
}
if (generalNameList.isEmpty()) {
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateTool.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateTool.java
index 60e3b3e556a..dd90df4dd6a 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateTool.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/CertificateTool.java
@@ -12,6 +12,7 @@ import joptsimple.OptionSpecBuilder;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMEncryptor;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder;
@@ -87,6 +88,7 @@ public class CertificateTool extends LoggingAwareMultiCommand {
private static final String DEFAULT_CERT_ZIP = "certificate-bundle.zip";
private static final String DEFAULT_CA_ZIP = "elastic-stack-ca.zip";
private static final String DEFAULT_CA_P12 = "elastic-stack-ca.p12";
+ private static final BouncyCastleProvider BC_PROV = new BouncyCastleProvider();
static final String DEFAULT_CERT_NAME = "instance";
@@ -334,7 +336,7 @@ public class CertificateTool extends LoggingAwareMultiCommand {
char[] passwordOption = getChars(caPasswordSpec.value(options));
Map keys = withPassword("CA (" + path + ")", passwordOption,
- terminal, password -> CertUtils.readPkcs12KeyPairs(path, password, a -> password, env));
+ terminal, password -> CertParsingUtils.readPkcs12KeyPairs(path, password, a -> password));
if (keys.size() != 1) {
throw new IllegalArgumentException("expected a single key in file [" + path.toAbsolutePath() + "] but found [" +
@@ -353,7 +355,7 @@ public class CertificateTool extends LoggingAwareMultiCommand {
String password = caPasswordSpec.value(options);
final String resolvedCaCertPath = cert.toAbsolutePath().toString();
- Certificate[] certificates = CertUtils.readCertificates(Collections.singletonList(resolvedCaCertPath), env);
+ Certificate[] certificates = CertParsingUtils.readCertificates(Collections.singletonList(resolvedCaCertPath), env);
if (certificates.length != 1) {
throw new IllegalArgumentException("expected a single certificate in file [" + resolvedCaCertPath + "] but found [" +
certificates.length + "]");
@@ -369,8 +371,8 @@ public class CertificateTool extends LoggingAwareMultiCommand {
dn = AUTO_GEN_CA_DN;
}
X500Principal x500Principal = new X500Principal(dn);
- KeyPair keyPair = CertUtils.generateKeyPair(getKeySize(options));
- X509Certificate caCert = CertUtils.generateCACertificate(x500Principal, keyPair, getDays(options));
+ KeyPair keyPair = CertGenUtils.generateKeyPair(getKeySize(options));
+ X509Certificate caCert = CertGenUtils.generateCACertificate(x500Principal, keyPair, getDays(options));
if (options.hasArgument(caPasswordSpec)) {
char[] password = getChars(caPasswordSpec.value(options));
@@ -612,10 +614,10 @@ public class CertificateTool extends LoggingAwareMultiCommand {
void generateAndWriteCsrs(Path output, int keySize, Collection certInfo) throws Exception {
fullyWriteZipFile(output, (outputStream, pemWriter) -> {
for (CertificateInformation certificateInformation : certInfo) {
- KeyPair keyPair = CertUtils.generateKeyPair(keySize);
+ KeyPair keyPair = CertGenUtils.generateKeyPair(keySize);
GeneralNames sanList = getSubjectAlternativeNamesValue(certificateInformation.ipAddresses,
certificateInformation.dnsNames, certificateInformation.commonNames);
- PKCS10CertificationRequest csr = CertUtils.generateCSR(keyPair, certificateInformation.name.x500Principal, sanList);
+ PKCS10CertificationRequest csr = CertGenUtils.generateCSR(keyPair, certificateInformation.name.x500Principal, sanList);
final String dirName = certificateInformation.name.filename + "/";
ZipEntry zipEntry = new ZipEntry(dirName);
@@ -819,8 +821,8 @@ public class CertificateTool extends LoggingAwareMultiCommand {
private CertificateAndKey generateCertificateAndKey(CertificateInformation certificateInformation, CAInfo caInfo,
int keySize, int days) throws Exception {
- KeyPair keyPair = CertUtils.generateKeyPair(keySize);
- Certificate certificate = CertUtils.generateSignedCertificate(certificateInformation.name.x500Principal,
+ KeyPair keyPair = CertGenUtils.generateKeyPair(keySize);
+ Certificate certificate = CertGenUtils.generateSignedCertificate(certificateInformation.name.x500Principal,
getSubjectAlternativeNamesValue(certificateInformation.ipAddresses, certificateInformation.dnsNames,
certificateInformation.commonNames),
keyPair, caInfo.certAndKey.cert, caInfo.certAndKey.key, days);
@@ -916,7 +918,7 @@ public class CertificateTool extends LoggingAwareMultiCommand {
}
private static PEMEncryptor getEncrypter(char[] password) {
- return new JcePEMEncryptorBuilder("DES-EDE3-CBC").setProvider(CertUtils.BC_PROV).build(password);
+ return new JcePEMEncryptorBuilder("DES-EDE3-CBC").setProvider(BC_PROV).build(password);
}
private static T withPassword(String description, char[] password, Terminal terminal,
@@ -1015,8 +1017,8 @@ public class CertificateTool extends LoggingAwareMultiCommand {
private static PrivateKey readPrivateKey(Path path, char[] password, Terminal terminal)
throws Exception {
AtomicReference passwordReference = new AtomicReference<>(password);
- try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
- return CertUtils.readPrivateKey(reader, () -> {
+ try {
+ return PemUtils.readPrivateKey(path, () -> {
if (password != null) {
return password;
}
@@ -1042,7 +1044,7 @@ public class CertificateTool extends LoggingAwareMultiCommand {
}
for (String cn : commonNames) {
- generalNameList.add(CertUtils.createCommonName(cn));
+ generalNameList.add(CertGenUtils.createCommonName(cn));
}
if (generalNameList.isEmpty()) {
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/DefaultJDKTrustConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/DefaultJDKTrustConfig.java
index 073fc06c137..ff818bb09f5 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/DefaultJDKTrustConfig.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/DefaultJDKTrustConfig.java
@@ -34,7 +34,7 @@ class DefaultJDKTrustConfig extends TrustConfig {
@Override
X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) {
try {
- return CertUtils.trustManager(null, TrustManagerFactory.getDefaultAlgorithm());
+ return CertParsingUtils.trustManager(null, TrustManagerFactory.getDefaultAlgorithm());
} catch (Exception e) {
throw new ElasticsearchException("failed to initialize a TrustManagerFactory", e);
}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/DerParser.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/DerParser.java
new file mode 100644
index 00000000000..fedbbb31947
--- /dev/null
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/DerParser.java
@@ -0,0 +1,285 @@
+/*
+ Copyright (c) 1998-2010 AOL Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ */
+
+package org.elasticsearch.xpack.core.ssl;
+
+
+import org.elasticsearch.common.hash.MessageDigests;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+
+/**
+ * A bare-minimum ASN.1 DER decoder, just having enough functions to
+ * decode PKCS#1 private keys in order to remain JCE/JVM agnostic.
+ *
+ * Based on https://github.com/groovenauts/jmeter_oauth_plugin/blob/master/jmeter/src/
+ * main/java/org/apache/jmeter/protocol/oauth/sampler/PrivateKeyReader.java
+ */
+class DerParser {
+ // Constructed Flag
+ private static final int CONSTRUCTED = 0x20;
+
+ // Tag and data types
+ private static final int INTEGER = 0x02;
+ private static final int OCTET_STRING = 0x04;
+ private static final int OBJECT_OID = 0x06;
+ private static final int NUMERIC_STRING = 0x12;
+ private static final int PRINTABLE_STRING = 0x13;
+ private static final int VIDEOTEX_STRING = 0x15;
+ private static final int IA5_STRING = 0x16;
+ private static final int GRAPHIC_STRING = 0x19;
+ private static final int ISO646_STRING = 0x1A;
+ private static final int GENERAL_STRING = 0x1B;
+
+ private static final int UTF8_STRING = 0x0C;
+ private static final int UNIVERSAL_STRING = 0x1C;
+ private static final int BMP_STRING = 0x1E;
+
+
+ private InputStream derInputStream;
+ private int maxAsnObjectLength;
+
+ DerParser(byte[] bytes) {
+ this.derInputStream = new ByteArrayInputStream(bytes);
+ this.maxAsnObjectLength = bytes.length;
+ }
+
+ Asn1Object readAsn1Object() throws IOException {
+ int tag = derInputStream.read();
+ if (tag == -1) {
+ throw new IOException("Invalid DER: stream too short, missing tag");
+ }
+ int length = getLength();
+ // getLength() can return any 32 bit integer, so ensure that a corrupted encoding won't
+ // force us into allocating a very large array
+ if (length > maxAsnObjectLength) {
+ throw new IOException("Invalid DER: size of ASN.1 object to be parsed appears to be larger than the size of the key file " +
+ "itself.");
+ }
+ byte[] value = new byte[length];
+ int n = derInputStream.read(value);
+ if (n < length) {
+ throw new IOException("Invalid DER: stream too short, missing value. " +
+ "Could only read " + n + " out of " + length + " bytes");
+ }
+ return new Asn1Object(tag, length, value);
+
+ }
+
+ /**
+ * Decode the length of the field. Can only support length
+ * encoding up to 4 octets.
+ *
+ *
In BER/DER encoding, length can be encoded in 2 forms,
+ *
+ * Short form. One octet. Bit 8 has value "0" and bits 7-1
+ * give the length.
+ *
+ * Long form. Two to 127 octets (only 4 is supported here).
+ * Bit 8 of first octet has value "1" and bits 7-1 give the
+ * number of additional length octets. Second and following
+ * octets give the length, base 256, most significant digit first.
+ *
+ *
+ *
+ * @return The length as integer
+ * @throws IOException
+ */
+ private int getLength() throws IOException {
+
+ int i = derInputStream.read();
+ if (i == -1)
+ throw new IOException("Invalid DER: length missing");
+
+ // A single byte short length
+ if ((i & ~0x7F) == 0)
+ return i;
+
+ int num = i & 0x7F;
+
+ // We can't handle length longer than 4 bytes
+ if (i >= 0xFF || num > 4)
+ throw new IOException("Invalid DER: length field too big ("
+ + i + ")"); //$NON-NLS-1$
+
+ byte[] bytes = new byte[num];
+ int n = derInputStream.read(bytes);
+ if (n < num)
+ throw new IOException("Invalid DER: length too short");
+
+ return new BigInteger(1, bytes).intValue();
+ }
+
+
+ /**
+ * An ASN.1 TLV. The object is not parsed. It can
+ * only handle integers.
+ *
+ * @author zhang
+ */
+ static class Asn1Object {
+
+ protected final int type;
+ protected final int length;
+ protected final byte[] value;
+ protected final int tag;
+
+ /**
+ * Construct a ASN.1 TLV. The TLV could be either a
+ * constructed or primitive entity.
+ *
+ *
The first byte in DER encoding is made of following fields,
+ *
+ * -------------------------------------------------
+ * |Bit 8|Bit 7|Bit 6|Bit 5|Bit 4|Bit 3|Bit 2|Bit 1|
+ * -------------------------------------------------
+ * | Class | CF | + Type |
+ * -------------------------------------------------
+ *
+ *
+ * Class: Universal, Application, Context or Private
+ * CF: Constructed flag. If 1, the field is constructed.
+ * Type: This is actually called tag in ASN.1. It
+ * indicates data type (Integer, String) or a construct
+ * (sequence, choice, set).
+ *
+ *
+ * @param tag Tag or Identifier
+ * @param length Length of the field
+ * @param value Encoded octet string for the field.
+ */
+ Asn1Object(int tag, int length, byte[] value) {
+ this.tag = tag;
+ this.type = tag & 0x1F;
+ this.length = length;
+ this.value = value;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public byte[] getValue() {
+ return value;
+ }
+
+ public boolean isConstructed() {
+ return (tag & DerParser.CONSTRUCTED) == DerParser.CONSTRUCTED;
+ }
+
+ /**
+ * For constructed field, return a parser for its content.
+ *
+ * @return A parser for the construct.
+ * @throws IOException
+ */
+ public DerParser getParser() throws IOException {
+ if (!isConstructed())
+ throw new IOException("Invalid DER: can't parse primitive entity"); //$NON-NLS-1$
+
+ return new DerParser(value);
+ }
+
+ /**
+ * Get the value as integer
+ *
+ * @return BigInteger
+ * @throws IOException
+ */
+ public BigInteger getInteger() throws IOException {
+ if (type != DerParser.INTEGER)
+ throw new IOException("Invalid DER: object is not integer"); //$NON-NLS-1$
+
+ return new BigInteger(value);
+ }
+
+ public String getString() throws IOException {
+
+ String encoding;
+
+ switch (type) {
+ case DerParser.OCTET_STRING:
+ // octet string is basically a byte array
+ return MessageDigests.toHexString(value);
+ case DerParser.NUMERIC_STRING:
+ case DerParser.PRINTABLE_STRING:
+ case DerParser.VIDEOTEX_STRING:
+ case DerParser.IA5_STRING:
+ case DerParser.GRAPHIC_STRING:
+ case DerParser.ISO646_STRING:
+ case DerParser.GENERAL_STRING:
+ encoding = "ISO-8859-1"; //$NON-NLS-1$
+ break;
+
+ case DerParser.BMP_STRING:
+ encoding = "UTF-16BE"; //$NON-NLS-1$
+ break;
+
+ case DerParser.UTF8_STRING:
+ encoding = "UTF-8"; //$NON-NLS-1$
+ break;
+
+ case DerParser.UNIVERSAL_STRING:
+ throw new IOException("Invalid DER: can't handle UCS-4 string"); //$NON-NLS-1$
+
+ default:
+ throw new IOException("Invalid DER: object is not a string"); //$NON-NLS-1$
+ }
+
+ return new String(value, encoding);
+ }
+
+ public String getOid() throws IOException {
+
+ if (type != DerParser.OBJECT_OID) {
+ throw new IOException("Ivalid DER: object is not object OID");
+ }
+ StringBuilder sb = new StringBuilder(64);
+ switch (value[0] / 40) {
+ case 0:
+ sb.append('0');
+ break;
+ case 1:
+ sb.append('1');
+ value[0] -= 40;
+ break;
+ default:
+ sb.append('2');
+ value[0] -= 80;
+ break;
+ }
+ int oidPart = 0;
+ for (int i = 0; i < length; i++) {
+ oidPart = (oidPart << 7) + (value[i] & 0x7F);
+ if ((value[i] & 0x80) == 0) {
+ sb.append('.');
+ sb.append(oidPart);
+ oidPart = 0;
+ }
+ }
+
+ return sb.toString();
+ }
+ }
+}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PEMKeyConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PEMKeyConfig.java
index c130d69b917..ab09b41af88 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PEMKeyConfig.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PEMKeyConfig.java
@@ -58,20 +58,20 @@ class PEMKeyConfig extends KeyConfig {
@Override
X509ExtendedKeyManager createKeyManager(@Nullable Environment environment) {
try {
- PrivateKey privateKey = readPrivateKey(CertUtils.resolvePath(keyPath, environment), keyPassword);
+ PrivateKey privateKey = readPrivateKey(CertParsingUtils.resolvePath(keyPath, environment), keyPassword);
if (privateKey == null) {
throw new IllegalArgumentException("private key [" + keyPath + "] could not be loaded");
}
Certificate[] certificateChain = getCertificateChain(environment);
- return CertUtils.keyManager(certificateChain, privateKey, keyPassword.getChars());
+ return CertParsingUtils.keyManager(certificateChain, privateKey, keyPassword.getChars());
} catch (IOException | UnrecoverableKeyException | NoSuchAlgorithmException | CertificateException | KeyStoreException e) {
throw new ElasticsearchException("failed to initialize a KeyManagerFactory", e);
}
}
private Certificate[] getCertificateChain(@Nullable Environment environment) throws CertificateException, IOException {
- return CertUtils.readCertificates(Collections.singletonList(certPath), environment);
+ return CertParsingUtils.readCertificates(Collections.singletonList(certPath), environment);
}
@Override
@@ -90,23 +90,21 @@ class PEMKeyConfig extends KeyConfig {
@Override
List privateKeys(@Nullable Environment environment) {
try {
- return Collections.singletonList(readPrivateKey(CertUtils.resolvePath(keyPath, environment), keyPassword));
+ return Collections.singletonList(readPrivateKey(CertParsingUtils.resolvePath(keyPath, environment), keyPassword));
} catch (IOException e) {
throw new UncheckedIOException("failed to read key", e);
}
}
private static PrivateKey readPrivateKey(Path keyPath, SecureString keyPassword) throws IOException {
- try (Reader reader = Files.newBufferedReader(keyPath, StandardCharsets.UTF_8)) {
- return CertUtils.readPrivateKey(reader, keyPassword::getChars);
- }
+ return PemUtils.readPrivateKey(keyPath, keyPassword::getChars);
}
@Override
X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) {
try {
Certificate[] certificates = getCertificateChain(environment);
- return CertUtils.trustManager(certificates);
+ return CertParsingUtils.trustManager(certificates);
} catch (Exception e) {
throw new ElasticsearchException("failed to initialize a TrustManagerFactory", e);
}
@@ -115,8 +113,8 @@ class PEMKeyConfig extends KeyConfig {
@Override
List filesToMonitor(@Nullable Environment environment) {
List paths = new ArrayList<>(2);
- paths.add(CertUtils.resolvePath(keyPath, environment));
- paths.add(CertUtils.resolvePath(certPath, environment));
+ paths.add(CertParsingUtils.resolvePath(keyPath, environment));
+ paths.add(CertParsingUtils.resolvePath(certPath, environment));
return paths;
}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PEMTrustConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PEMTrustConfig.java
index e191d0e1547..1fd163c9915 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PEMTrustConfig.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PEMTrustConfig.java
@@ -42,8 +42,8 @@ class PEMTrustConfig extends TrustConfig {
@Override
X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) {
try {
- Certificate[] certificates = CertUtils.readCertificates(caPaths, environment);
- return CertUtils.trustManager(certificates);
+ Certificate[] certificates = CertParsingUtils.readCertificates(caPaths, environment);
+ return CertParsingUtils.trustManager(certificates);
} catch (Exception e) {
throw new ElasticsearchException("failed to initialize a TrustManagerFactory", e);
}
@@ -53,7 +53,7 @@ class PEMTrustConfig extends TrustConfig {
Collection certificates(Environment environment) throws CertificateException, IOException {
final List info = new ArrayList<>(caPaths.size());
for (String path : caPaths) {
- Certificate[] chain = CertUtils.readCertificates(Collections.singletonList(path), environment);
+ Certificate[] chain = CertParsingUtils.readCertificates(Collections.singletonList(path), environment);
for (final Certificate cert : chain) {
if (cert instanceof X509Certificate) {
info.add(new CertificateInfo(path, "PEM", null, false, (X509Certificate) cert));
@@ -67,7 +67,7 @@ class PEMTrustConfig extends TrustConfig {
List filesToMonitor(@Nullable Environment environment) {
List paths = new ArrayList<>(caPaths.size());
for (String path : caPaths) {
- paths.add(CertUtils.resolvePath(path, environment));
+ paths.add(CertParsingUtils.resolvePath(path, environment));
}
return paths;
}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PemUtils.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PemUtils.java
new file mode 100644
index 00000000000..9ff44d0135f
--- /dev/null
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/PemUtils.java
@@ -0,0 +1,559 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+package org.elasticsearch.xpack.core.ssl;
+
+import org.elasticsearch.common.hash.MessageDigests;
+import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
+import java.security.PrivateKey;
+import java.security.interfaces.ECKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.DSAPrivateKeySpec;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPrivateKeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.util.Arrays;
+import java.util.Base64;
+
+import javax.crypto.Cipher;
+import javax.crypto.EncryptedPrivateKeyInfo;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Supplier;
+
+public class PemUtils {
+
+ private static final String PKCS1_HEADER = "-----BEGIN RSA PRIVATE KEY-----";
+ private static final String PKCS1_FOOTER = "-----END RSA PRIVATE KEY-----";
+ private static final String OPENSSL_DSA_HEADER = "-----BEGIN DSA PRIVATE KEY-----";
+ private static final String OPENSSL_DSA_FOOTER = "-----END DSA PRIVATE KEY-----";
+ private static final String OPENSSL_DSA_PARAMS_HEADER ="-----BEGIN DSA PARAMETERS-----";
+ private static final String OPENSSL_DSA_PARAMS_FOOTER ="-----END DSA PARAMETERS-----";
+ private static final String PKCS8_HEADER = "-----BEGIN PRIVATE KEY-----";
+ private static final String PKCS8_FOOTER = "-----END PRIVATE KEY-----";
+ private static final String PKCS8_ENCRYPTED_HEADER = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+ private static final String PKCS8_ENCRYPTED_FOOTER = "-----END ENCRYPTED PRIVATE KEY-----";
+ private static final String OPENSSL_EC_HEADER = "-----BEGIN EC PRIVATE KEY-----";
+ private static final String OPENSSL_EC_FOOTER = "-----END EC PRIVATE KEY-----";
+ private static final String OPENSSL_EC_PARAMS_HEADER = "-----BEGIN EC PARAMETERS-----";
+ private static final String OPENSSL_EC_PARAMS_FOOTER = "-----END EC PARAMETERS-----";
+
+ private PemUtils() {
+ throw new IllegalStateException("Utility class should not be instantiated");
+ }
+
+ /**
+ * Creates a {@link PrivateKey} from the contents of a file. Supports PKCS#1, PKCS#8
+ * encoded formats of encrypted and plaintext RSA, DSA and EC(secp256r1) keys
+ *
+ * @param keyPath the path for the key file
+ * @param passwordSupplier A password supplier for the potentially encrypted (password protected) key
+ * @return a private key from the contents of the file
+ */
+ public static PrivateKey readPrivateKey(Path keyPath, Supplier passwordSupplier) {
+ try (BufferedReader bReader = Files.newBufferedReader(keyPath, StandardCharsets.UTF_8)) {
+ String line = bReader.readLine();
+ if (null == line) {
+ throw new IllegalStateException("Error parsing Private Key from: " + keyPath.toString() + ". File is empty");
+ }
+ if (PKCS8_ENCRYPTED_HEADER.equals(line.trim())) {
+ char[] password = passwordSupplier.get();
+ if (password == null) {
+ throw new IllegalArgumentException("cannot read encrypted key without a password");
+ }
+ return parsePKCS8Encrypted(bReader, password);
+ } else if (PKCS8_HEADER.equals(line.trim())) {
+ return parsePKCS8(bReader);
+ } else if (PKCS1_HEADER.equals(line.trim())) {
+ return parsePKCS1Rsa(bReader, passwordSupplier);
+ } else if (OPENSSL_DSA_HEADER.equals(line.trim())) {
+ return parseOpenSslDsa(bReader, passwordSupplier);
+ } else if (OPENSSL_DSA_PARAMS_HEADER.equals(line.trim())) {
+ return parseOpenSslDsa(removeDsaHeaders(bReader), passwordSupplier);
+ } else if (OPENSSL_EC_HEADER.equals(line.trim())) {
+ return parseOpenSslEC(bReader, passwordSupplier);
+ } else if (OPENSSL_EC_PARAMS_HEADER.equals(line.trim())) {
+ return parseOpenSslEC(removeECHeaders(bReader), passwordSupplier);
+ } else {
+ throw new IllegalStateException("Error parsing Private Key from: " + keyPath.toString() + ". File did not contain a " +
+ "supported key format");
+ }
+ } catch (IOException | GeneralSecurityException e) {
+ throw new IllegalStateException("Error parsing Private Key from: " + keyPath.toString(), e);
+ }
+ }
+
+ /**
+ * Removes the EC Headers that OpenSSL adds to EC private keys as the information in them
+ * is redundant
+ *
+ * @param bReader
+ * @throws IOException if the EC Parameter footer is missing
+ */
+ private static BufferedReader removeECHeaders(BufferedReader bReader) throws IOException {
+ String line = bReader.readLine();
+ while (line != null) {
+ if (OPENSSL_EC_PARAMS_FOOTER.equals(line.trim())) {
+ break;
+ }
+ line = bReader.readLine();
+ }
+ if (null == line || OPENSSL_EC_PARAMS_FOOTER.equals(line.trim()) == false) {
+ throw new IOException("Malformed PEM file, EC Parameters footer is missing");
+ }
+ // Verify that the key starts with the correct header before passing it to parseOpenSslEC
+ if (OPENSSL_EC_HEADER.equals(bReader.readLine()) == false) {
+ throw new IOException("Malformed PEM file, EC Key header is missing");
+ }
+ return bReader;
+ }
+
+ /**
+ * Removes the DSA Params Headers that OpenSSL adds to DSA private keys as the information in them
+ * is redundant
+ *
+ * @param bReader
+ * @throws IOException if the EC Parameter footer is missing
+ */
+ private static BufferedReader removeDsaHeaders(BufferedReader bReader) throws IOException {
+ String line = bReader.readLine();
+ while (line != null) {
+ if (OPENSSL_DSA_PARAMS_FOOTER.equals(line.trim())) {
+ break;
+ }
+ line = bReader.readLine();
+ }
+ if (null == line || OPENSSL_DSA_PARAMS_FOOTER.equals(line.trim()) == false) {
+ throw new IOException("Malformed PEM file, DSA Parameters footer is missing");
+ }
+ // Verify that the key starts with the correct header before passing it to parseOpenSslDsa
+ if (OPENSSL_DSA_HEADER.equals(bReader.readLine()) == false) {
+ throw new IOException("Malformed PEM file, DSA Key header is missing");
+ }
+ return bReader;
+ }
+
+ /**
+ * Creates a {@link PrivateKey} from the contents of {@code bReader} that contains an plaintext private key encoded in
+ * PKCS#8
+ *
+ * @param bReader the {@link BufferedReader} containing the key file contents
+ * @return {@link PrivateKey}
+ * @throws IOException if the file can't be read
+ * @throws GeneralSecurityException if the private key can't be generated from the {@link PKCS8EncodedKeySpec}
+ */
+ private static PrivateKey parsePKCS8(BufferedReader bReader) throws IOException, GeneralSecurityException {
+ StringBuilder sb = new StringBuilder();
+ String line = bReader.readLine();
+ while (line != null) {
+ if (PKCS8_FOOTER.equals(line.trim())) {
+ break;
+ }
+ sb.append(line.trim());
+ line = bReader.readLine();
+ }
+ if (null == line || PKCS8_FOOTER.equals(line.trim()) == false) {
+ throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
+ }
+ byte[] keyBytes = Base64.getDecoder().decode(sb.toString());
+ String keyAlgo = getKeyAlgorithmIdentifier(keyBytes);
+ KeyFactory keyFactory = KeyFactory.getInstance(keyAlgo);
+ return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
+ }
+
+ /**
+ * Creates a {@link PrivateKey} from the contents of {@code bReader} that contains an EC private key encoded in
+ * OpenSSL traditional format.
+ *
+ * @param bReader the {@link BufferedReader} containing the key file contents
+ * @param passwordSupplier A password supplier for the potentially encrypted (password protected) key
+ * @return {@link PrivateKey}
+ * @throws IOException if the file can't be read
+ * @throws GeneralSecurityException if the private key can't be generated from the {@link ECPrivateKeySpec}
+ */
+ private static PrivateKey parseOpenSslEC(BufferedReader bReader, Supplier passwordSupplier) throws IOException,
+ GeneralSecurityException {
+ StringBuilder sb = new StringBuilder();
+ String line = bReader.readLine();
+ Map pemHeaders = new HashMap<>();
+ while (line != null) {
+ if (OPENSSL_EC_FOOTER.equals(line.trim())) {
+ break;
+ }
+ // Parse PEM headers according to https://www.ietf.org/rfc/rfc1421.txt
+ if (line.contains(":")) {
+ String[] header = line.split(":");
+ pemHeaders.put(header[0].trim(), header[1].trim());
+ } else {
+ sb.append(line.trim());
+ }
+ line = bReader.readLine();
+ }
+ if (null == line || OPENSSL_EC_FOOTER.equals(line.trim()) == false) {
+ throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
+ }
+ byte[] keyBytes = possiblyDecryptPKCS1Key(pemHeaders, sb.toString(), passwordSupplier);
+ KeyFactory keyFactory = KeyFactory.getInstance("EC");
+ ECPrivateKeySpec ecSpec = parseEcDer(keyBytes);
+ return keyFactory.generatePrivate(ecSpec);
+ }
+
+ /**
+ * Creates a {@link PrivateKey} from the contents of {@code bReader} that contains an RSA private key encoded in
+ * OpenSSL traditional format.
+ *
+ * @param bReader the {@link BufferedReader} containing the key file contents
+ * @param passwordSupplier A password supplier for the potentially encrypted (password protected) key
+ * @return {@link PrivateKey}
+ * @throws IOException if the file can't be read
+ * @throws GeneralSecurityException if the private key can't be generated from the {@link RSAPrivateCrtKeySpec}
+ */
+ private static PrivateKey parsePKCS1Rsa(BufferedReader bReader, Supplier passwordSupplier) throws IOException,
+ GeneralSecurityException {
+ StringBuilder sb = new StringBuilder();
+ String line = bReader.readLine();
+ Map pemHeaders = new HashMap<>();
+
+ while (line != null) {
+ if (PKCS1_FOOTER.equals(line.trim())) {
+ // Unencrypted
+ break;
+ }
+ // Parse PEM headers according to https://www.ietf.org/rfc/rfc1421.txt
+ if (line.contains(":")) {
+ String[] header = line.split(":");
+ pemHeaders.put(header[0].trim(), header[1].trim());
+ } else {
+ sb.append(line.trim());
+ }
+ line = bReader.readLine();
+ }
+ if (null == line || PKCS1_FOOTER.equals(line.trim()) == false) {
+ throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
+ }
+ byte[] keyBytes = possiblyDecryptPKCS1Key(pemHeaders, sb.toString(), passwordSupplier);
+ RSAPrivateCrtKeySpec spec = parseRsaDer(keyBytes);
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ return keyFactory.generatePrivate(spec);
+ }
+
+ /**
+ * Creates a {@link PrivateKey} from the contents of {@code bReader} that contains an DSA private key encoded in
+ * OpenSSL traditional format.
+ *
+ * @param bReader the {@link BufferedReader} containing the key file contents
+ * @param passwordSupplier A password supplier for the potentially encrypted (password protected) key
+ * @return {@link PrivateKey}
+ * @throws IOException if the file can't be read
+ * @throws GeneralSecurityException if the private key can't be generated from the {@link DSAPrivateKeySpec}
+ */
+ private static PrivateKey parseOpenSslDsa(BufferedReader bReader, Supplier passwordSupplier) throws IOException,
+ GeneralSecurityException {
+ StringBuilder sb = new StringBuilder();
+ String line = bReader.readLine();
+ Map pemHeaders = new HashMap<>();
+
+ while (line != null) {
+ if (OPENSSL_DSA_FOOTER.equals(line.trim())) {
+ // Unencrypted
+ break;
+ }
+ // Parse PEM headers according to https://www.ietf.org/rfc/rfc1421.txt
+ if (line.contains(":")) {
+ String[] header = line.split(":");
+ pemHeaders.put(header[0].trim(), header[1].trim());
+ } else {
+ sb.append(line.trim());
+ }
+ line = bReader.readLine();
+ }
+ if (null == line || OPENSSL_DSA_FOOTER.equals(line.trim()) == false) {
+ throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
+ }
+ byte[] keyBytes = possiblyDecryptPKCS1Key(pemHeaders, sb.toString(), passwordSupplier);
+ DSAPrivateKeySpec spec = parseDsaDer(keyBytes);
+ KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+ return keyFactory.generatePrivate(spec);
+ }
+
+ /**
+ * Creates a {@link PrivateKey} from the contents of {@code bReader} that contains an encrypted private key encoded in
+ * PKCS#8
+ *
+ * @param bReader the {@link BufferedReader} containing the key file contents
+ * @param keyPassword The password for the encrypted (password protected) key
+ * @return {@link PrivateKey}
+ * @throws IOException if the file can't be read
+ * @throws GeneralSecurityException if the private key can't be generated from the {@link PKCS8EncodedKeySpec}
+ */
+ private static PrivateKey parsePKCS8Encrypted(BufferedReader bReader, char[] keyPassword) throws IOException,
+ GeneralSecurityException {
+ StringBuilder sb = new StringBuilder();
+ String line = bReader.readLine();
+ while (line != null) {
+ if (PKCS8_ENCRYPTED_FOOTER.equals(line.trim())) {
+ break;
+ }
+ sb.append(line.trim());
+ line = bReader.readLine();
+ }
+ if (null == line || PKCS8_ENCRYPTED_FOOTER.equals(line.trim()) == false) {
+ throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
+ }
+ byte[] keyBytes = Base64.getDecoder().decode(sb.toString());
+
+ EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(keyBytes);
+ SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(encryptedPrivateKeyInfo.getAlgName());
+ SecretKey secretKey = secretKeyFactory.generateSecret(new PBEKeySpec(keyPassword));
+ Arrays.fill(keyPassword, '\u0000');
+ Cipher cipher = Cipher.getInstance(encryptedPrivateKeyInfo.getAlgName());
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, encryptedPrivateKeyInfo.getAlgParameters());
+ PKCS8EncodedKeySpec keySpec = encryptedPrivateKeyInfo.getKeySpec(cipher);
+ String keyAlgo = getKeyAlgorithmIdentifier(keySpec.getEncoded());
+ KeyFactory keyFactory = KeyFactory.getInstance(keyAlgo);
+ return keyFactory.generatePrivate(keySpec);
+ }
+
+ /**
+ * Decrypts the password protected contents using the algorithm and IV that is specified in the PEM Headers of the file
+ *
+ * @param pemHeaders The Proc-Type and DEK-Info PEM headers that have been extracted from the key file
+ * @param keyContents The key as a base64 encoded String
+ * @param passwordSupplier A password supplier for the encrypted (password protected) key
+ * @return the decrypted key bytes
+ * @throws GeneralSecurityException if the key can't be decrypted
+ * @throws IOException if the PEM headers are missing or malformed
+ */
+ private static byte[] possiblyDecryptPKCS1Key(Map pemHeaders, String keyContents, Supplier passwordSupplier)
+ throws GeneralSecurityException, IOException {
+ byte[] keyBytes = Base64.getDecoder().decode(keyContents);
+ String procType = pemHeaders.get("Proc-Type");
+ if ("4,ENCRYPTED".equals(procType)) {
+ //We only handle PEM encryption
+ String encryptionParameters = pemHeaders.get("DEK-Info");
+ if (null == encryptionParameters) {
+ //malformed pem
+ throw new IOException("Malformed PEM File, DEK-Info header is missing");
+ }
+ char[] password = passwordSupplier.get();
+ if (password == null) {
+ throw new IOException("cannot read encrypted key without a password");
+ }
+ Cipher cipher = getCipherFromParameters(encryptionParameters, password);
+ byte[] decryptedKeyBytes = cipher.doFinal(keyBytes);
+ return decryptedKeyBytes;
+ }
+ return keyBytes;
+ }
+
+ /**
+ * Creates a {@link Cipher} from the contents of the DEK-Info header of a PEM file. RFC 1421 indicates that supported algorithms are
+ * defined in RFC 1423. RFC 1423 only defines DES-CBS and triple DES (EDE) in CBC mode. AES in CBC mode is also widely used though ( 3
+ * different variants of 128, 192, 256 bit keys )
+ *
+ * @param dekHeaderValue The value of the the DEK-Info PEM header
+ * @param password The password with which the key is encrypted
+ * @return a cipher of the appropriate algorithm and parameters to be used for decryption
+ * @throws GeneralSecurityException if the algorithm is not available in the used security provider, or if the key is inappropriate
+ * for the cipher
+ * @throws IOException if the DEK-Info PEM header is invalid
+ */
+ private static Cipher getCipherFromParameters(String dekHeaderValue, char[] password) throws
+ GeneralSecurityException, IOException {
+ String padding = "PKCS5Padding";
+ SecretKey encryptionKey;
+ String[] valueTokens = dekHeaderValue.split(",");
+ if (valueTokens.length != 2) {
+ throw new IOException("Malformed PEM file, DEK-Info PEM header is invalid");
+ }
+ String algorithm = valueTokens[0];
+ String ivString = valueTokens[1];
+ byte[] iv = hexStringToByteArray(ivString);
+ if ("DES-CBC".equals(algorithm)) {
+ byte[] key = generateOpenSslKey(password, iv, 8);
+ encryptionKey = new SecretKeySpec(key, "DES");
+ } else if ("DES-EDE3-CBC".equals(algorithm)) {
+ byte[] key = generateOpenSslKey(password, iv, 24);
+ encryptionKey = new SecretKeySpec(key, "DESede");
+ } else if ("AES-128-CBC".equals(algorithm)) {
+ byte[] key = generateOpenSslKey(password, iv, 16);
+ encryptionKey = new SecretKeySpec(key, "AES");
+ } else if ("AES-192-CBC".equals(algorithm)) {
+ byte[] key = generateOpenSslKey(password, iv, 24);
+ encryptionKey = new SecretKeySpec(key, "AES");
+ } else if ("AES-256-CBC".equals(algorithm)) {
+ byte[] key = generateOpenSslKey(password, iv, 32);
+ encryptionKey = new SecretKeySpec(key, "AES");
+ } else {
+ throw new GeneralSecurityException("Private Key encrypted with unsupported algorithm: " + algorithm);
+ }
+ String transformation = encryptionKey.getAlgorithm() + "/" + "CBC" + "/" + padding;
+ Cipher cipher = Cipher.getInstance(transformation);
+ cipher.init(Cipher.DECRYPT_MODE, encryptionKey, new IvParameterSpec(iv));
+ return cipher;
+ }
+
+ /**
+ * Performs key stretching in the same manner that OpenSSL does. This is basically a KDF
+ * that uses n rounds of salted MD5 (as many times as needed to get the necessary number of key bytes)
+ *
+ * https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_PrivateKey_traditional.html
+ */
+ private static byte[] generateOpenSslKey(char[] password, byte[] salt, int keyLength) {
+ byte[] passwordBytes = CharArrays.toUtf8Bytes(password);
+ MessageDigest md5 = MessageDigests.md5();
+ byte[] key = new byte[keyLength];
+ int copied = 0;
+ int remaining;
+ while (copied < keyLength) {
+ remaining = keyLength - copied;
+ md5.update(passwordBytes, 0, passwordBytes.length);
+ md5.update(salt, 0, 8);// AES IV (salt) is longer but we only need 8 bytes
+ byte[] tempDigest = md5.digest();
+ int bytesToCopy = (remaining > 16) ? 16 : remaining; // MD5 digests are 16 bytes
+ System.arraycopy(tempDigest, 0, key, copied, bytesToCopy);
+ copied += bytesToCopy;
+ if (remaining == 0) {
+ break;
+ }
+ md5.update(tempDigest, 0, 16); // use previous round digest as IV
+ }
+ Arrays.fill(passwordBytes, (byte) 0);
+ return key;
+ }
+
+ /**
+ * Converts a hexadecimal string to a byte array
+ */
+ private static byte[] hexStringToByteArray(String hexString) {
+ int len = hexString.length();
+ if (len % 2 == 0) {
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ final int k = Character.digit(hexString.charAt(i), 16);
+ final int l = Character.digit(hexString.charAt(i + 1), 16);
+ if (k == -1 || l == -1) {
+ throw new IllegalStateException("String is not hexadecimal");
+ }
+ data[i / 2] = (byte) ((k << 4) + l);
+ }
+ return data;
+ } else {
+ throw new IllegalStateException("Hexadeciamal string length is odd, can't convert to byte array");
+ }
+ }
+
+ /**
+ * Parses a DER encoded EC key to an {@link ECPrivateKeySpec} using a minimal {@link DerParser}
+ *
+ * @param keyBytes the private key raw bytes
+ * @return {@link ECPrivateKeySpec}
+ * @throws IOException if the DER encoded key can't be parsed
+ */
+ private static ECPrivateKeySpec parseEcDer(byte[] keyBytes) throws IOException,
+ GeneralSecurityException {
+ DerParser parser = new DerParser(keyBytes);
+ DerParser.Asn1Object sequence = parser.readAsn1Object();
+ parser = sequence.getParser();
+ parser.readAsn1Object().getInteger(); // version
+ String keyHex = parser.readAsn1Object().getString();
+ BigInteger privateKeyInt = new BigInteger(keyHex, 16);
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
+ AlgorithmParameterSpec prime256v1ParamSpec = new ECGenParameterSpec("secp256r1");
+ keyPairGenerator.initialize(prime256v1ParamSpec);
+ ECParameterSpec parameterSpec = ((ECKey) keyPairGenerator.generateKeyPair().getPrivate()).getParams();
+ return new ECPrivateKeySpec(privateKeyInt, parameterSpec);
+ }
+
+ /**
+ * Parses a DER encoded RSA key to a {@link RSAPrivateCrtKeySpec} using a minimal {@link DerParser}
+ *
+ * @param keyBytes the private key raw bytes
+ * @return {@link RSAPrivateCrtKeySpec}
+ * @throws IOException if the DER encoded key can't be parsed
+ */
+ private static RSAPrivateCrtKeySpec parseRsaDer(byte[] keyBytes) throws IOException {
+ DerParser parser = new DerParser(keyBytes);
+ DerParser.Asn1Object sequence = parser.readAsn1Object();
+ parser = sequence.getParser();
+ parser.readAsn1Object().getInteger(); // (version) We don't need it but must read to get to modulus
+ BigInteger modulus = parser.readAsn1Object().getInteger();
+ BigInteger publicExponent = parser.readAsn1Object().getInteger();
+ BigInteger privateExponent = parser.readAsn1Object().getInteger();
+ BigInteger prime1 = parser.readAsn1Object().getInteger();
+ BigInteger prime2 = parser.readAsn1Object().getInteger();
+ BigInteger exponent1 = parser.readAsn1Object().getInteger();
+ BigInteger exponent2 = parser.readAsn1Object().getInteger();
+ BigInteger coefficient = parser.readAsn1Object().getInteger();
+ return new RSAPrivateCrtKeySpec(modulus, publicExponent, privateExponent, prime1, prime2, exponent1, exponent2, coefficient);
+ }
+
+ /**
+ * Parses a DER encoded DSA key to a {@link DSAPrivateKeySpec} using a minimal {@link DerParser}
+ *
+ * @param keyBytes the private key raw bytes
+ * @return {@link DSAPrivateKeySpec}
+ * @throws IOException if the DER encoded key can't be parsed
+ */
+ private static DSAPrivateKeySpec parseDsaDer(byte[] keyBytes) throws IOException {
+ DerParser parser = new DerParser(keyBytes);
+ DerParser.Asn1Object sequence = parser.readAsn1Object();
+ parser = sequence.getParser();
+ parser.readAsn1Object().getInteger(); // (version) We don't need it but must read to get to p
+ BigInteger p = parser.readAsn1Object().getInteger();
+ BigInteger q = parser.readAsn1Object().getInteger();
+ BigInteger g = parser.readAsn1Object().getInteger();
+ parser.readAsn1Object().getInteger(); // we don't need x
+ BigInteger x = parser.readAsn1Object().getInteger();
+ return new DSAPrivateKeySpec(x, p, q, g);
+ }
+
+ /**
+ * Parses a DER encoded private key and reads its algorithm identifier Object OID.
+ *
+ * @param keyBytes the private key raw bytes
+ * @return A string identifier for the key algorithm (RSA, DSA, or EC)
+ * @throws GeneralSecurityException if the algorithm oid that is parsed from ASN.1 is unknown
+ * @throws IOException if the DER encoded key can't be parsed
+ */
+ private static String getKeyAlgorithmIdentifier(byte[] keyBytes) throws IOException, GeneralSecurityException {
+ DerParser parser = new DerParser(keyBytes);
+ DerParser.Asn1Object sequence = parser.readAsn1Object();
+ parser = sequence.getParser();
+ parser.readAsn1Object().getInteger(); // version
+ DerParser.Asn1Object algSequence = parser.readAsn1Object();
+ parser = algSequence.getParser();
+ String oidString = parser.readAsn1Object().getOid();
+ switch (oidString) {
+ case "1.2.840.10040.4.1":
+ return "DSA";
+ case "1.2.840.113549.1.1.1":
+ return "RSA";
+ case "1.2.840.10045.2.1":
+ return "EC";
+ }
+ throw new GeneralSecurityException("Error parsing key algorithm identifier. Algorithm with OID: "+oidString+ " is not " +
+ "supported");
+ }
+}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustConfig.java
index 85022fde928..201965b4188 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustConfig.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustConfig.java
@@ -85,7 +85,7 @@ public final class RestrictedTrustConfig extends TrustConfig {
}
private Path resolveGroupConfigPath(@Nullable Environment environment) {
- return CertUtils.resolvePath(groupConfigPath, environment);
+ return CertParsingUtils.resolvePath(groupConfigPath, environment);
}
private CertificateTrustRestrictions readTrustGroup(Path path) throws IOException {
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManager.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManager.java
index 895642dd557..c49692dda98 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManager.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManager.java
@@ -7,18 +7,13 @@ package org.elasticsearch.xpack.core.ssl;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.X509ExtendedTrustManager;
+import java.io.IOException;
import java.net.Socket;
import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
@@ -41,10 +36,11 @@ import java.util.stream.Collectors;
*/
public final class RestrictedTrustManager extends X509ExtendedTrustManager {
+ private static final String CN_OID = "2.5.4.3";
+ private static final int SAN_CODE_OTHERNAME = 0;
private final Logger logger;
private final X509ExtendedTrustManager delegate;
private final CertificateTrustRestrictions trustRestrictions;
- private final int SAN_CODE_OTHERNAME = 0;
public RestrictedTrustManager(Settings settings, X509ExtendedTrustManager delegate, CertificateTrustRestrictions restrictions) {
this.logger = Loggers.getLogger(getClass(), settings);
@@ -127,47 +123,54 @@ public final class RestrictedTrustManager extends X509ExtendedTrustManager {
return getSubjectAlternativeNames(certificate).stream()
.filter(pair -> ((Integer) pair.get(0)).intValue() == SAN_CODE_OTHERNAME)
.map(pair -> pair.get(1))
- .map(value -> {
- ASN1Sequence seq = ASN1Sequence.getInstance(value);
- if (seq.size() != 2) {
- String message = "Incorrect sequence length for 'other name' [" + seq + "]";
- assert false : message;
- logger.warn(message);
- return null;
- }
- final String id = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)).getId();
- if (CertUtils.CN_OID.equals(id)) {
- ASN1TaggedObject tagged = DERTaggedObject.getInstance(seq.getObjectAt(1));
- // The JRE's handling of OtherNames is buggy.
- // The internal sun classes go to a lot of trouble to parse the GeneralNames into real object
- // And then java.security.cert.X509Certificate just turns them back into bytes
- // But in doing so, it ends up wrapping the "other name" bytes with a second tag
- // Specifically: sun.security.x509.OtherName(DerValue) never decodes the tagged "nameValue"
- // But: sun.security.x509.OtherName.encode() wraps the nameValue in a DER Tag.
- // So, there's a good chance that our tagged nameValue contains... a tagged name value.
- if (tagged.getObject() instanceof ASN1TaggedObject) {
- tagged = (ASN1TaggedObject) tagged.getObject();
- }
- final ASN1Primitive nameValue = tagged.getObject();
- if (nameValue instanceof ASN1String) {
- final String cn = ((ASN1String) nameValue).getString();
- logger.trace("Read cn [{}] from ASN1Sequence [{}]", cn, seq);
- return cn;
- } else {
- logger.warn("Certificate [{}] has 'otherName' [{}] with unsupported name-value type [{}]",
- certificate.getSubjectDN(), seq, nameValue.getClass().getSimpleName());
- return null;
- }
- } else {
- logger.debug("Certificate [{}] has 'otherName' [{}] with unsupported object-id [{}]",
- certificate.getSubjectDN(), seq, id);
- return null;
- }
- })
+ .map(value -> decodeDerValue((byte[]) value, certificate))
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
+ /**
+ * Decodes the otherName CN from the certificate
+ *
+ * @param value The DER Encoded Subject Alternative Name
+ * @param certificate
+ * @return the CN or null if it could not be parsed
+ */
+ private String decodeDerValue(byte[] value, X509Certificate certificate) {
+ try {
+ DerParser parser = new DerParser(value);
+ DerParser.Asn1Object seq = parser.readAsn1Object();
+ parser = seq.getParser();
+ String id = parser.readAsn1Object().getOid();
+ if (CN_OID.equals(id)) {
+ // Get the DER object with explicit 0 tag
+ DerParser.Asn1Object cnObject = parser.readAsn1Object();
+ parser = cnObject.getParser();
+ // The JRE's handling of OtherNames is buggy.
+ // The internal sun classes go to a lot of trouble to parse the GeneralNames into real object
+ // And then java.security.cert.X509Certificate just turns them back into bytes
+ // But in doing so, it ends up wrapping the "other name" bytes with a second tag
+ // Specifically: sun.security.x509.OtherName(DerValue) never decodes the tagged "nameValue"
+ // But: sun.security.x509.OtherName.encode() wraps the nameValue in a DER Tag.
+ // So, there's a good chance that our tagged nameValue contains... a tagged name value.
+ DerParser.Asn1Object innerObject = parser.readAsn1Object();
+ if (innerObject.isConstructed()) {
+ innerObject = innerObject.getParser().readAsn1Object();
+ }
+ logger.trace("Read innermost ASN.1 Object with type code [{}]", innerObject.getType());
+ String cn = innerObject.getString();
+ logger.trace("Read cn [{}] from ASN1Sequence [{}]", cn, seq);
+ return cn;
+ } else {
+ logger.debug("Certificate [{}] has 'otherName' [{}] with unsupported object-id [{}]",
+ certificate.getSubjectDN(), seq, id);
+ return null;
+ }
+ } catch (IOException e) {
+ logger.warn("Failed to read 'otherName' from certificate [{}]",
+ certificate.getSubjectDN());
+ return null;
+ }
+ }
private Collection> getSubjectAlternativeNames(X509Certificate certificate) throws CertificateParsingException {
final Collection> sans = certificate.getSubjectAlternativeNames();
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLConfiguration.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLConfiguration.java
index a9ba62998bd..0f91abac2a7 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLConfiguration.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLConfiguration.java
@@ -184,7 +184,7 @@ public final class SSLConfiguration {
private static KeyConfig createKeyConfig(Settings settings, SSLConfiguration global) {
final String trustStoreAlgorithm = SETTINGS_PARSER.truststoreAlgorithm.get(settings);
- final KeyConfig config = CertUtils.createKeyConfig(SETTINGS_PARSER.x509KeyPair, settings, trustStoreAlgorithm);
+ final KeyConfig config = CertParsingUtils.createKeyConfig(SETTINGS_PARSER.x509KeyPair, settings, trustStoreAlgorithm);
if (config != null) {
return config;
}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java
index e5150e3faad..9cb285b9394 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java
@@ -589,9 +589,9 @@ public class SSLService extends AbstractComponent {
private void reloadSslContext() {
try {
X509ExtendedKeyManager loadedKeyManager = Optional.ofNullable(keyConfig.createKeyManager(env)).
- orElse(getEmptyKeyManager());
+ orElse(getEmptyKeyManager());
X509ExtendedTrustManager loadedTrustManager = Optional.ofNullable(trustConfig.createTrustManager(env)).
- orElse(getEmptyTrustManager());
+ orElse(getEmptyTrustManager());
SSLContext loadedSslContext = SSLContext.getInstance(sslContextAlgorithm(sslConfiguration.supportedProtocols()));
loadedSslContext.init(new X509ExtendedKeyManager[]{loadedKeyManager},
new X509ExtendedTrustManager[]{loadedTrustManager}, null);
@@ -601,6 +601,7 @@ public class SSLService extends AbstractComponent {
throw new ElasticsearchException("failed to initialize the SSLContext", e);
}
}
+
X509ExtendedKeyManager getEmptyKeyManager() throws GeneralSecurityException, IOException {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfig.java
index ea9c9267d65..a47745c1334 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfig.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfig.java
@@ -73,7 +73,7 @@ class StoreKeyConfig extends KeyConfig {
try {
KeyStore ks = getKeyStore(environment);
checkKeyStore(ks);
- return CertUtils.keyManager(ks, keyPassword.getChars(), keyStoreAlgorithm);
+ return CertParsingUtils.keyManager(ks, keyPassword.getChars(), keyStoreAlgorithm);
} catch (IOException | CertificateException | NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) {
throw new ElasticsearchException("failed to initialize a KeyManagerFactory", e);
}
@@ -82,7 +82,7 @@ class StoreKeyConfig extends KeyConfig {
@Override
X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) {
try {
- return CertUtils.trustManager(keyStorePath, keyStoreType, keyStorePassword.getChars(), trustStoreAlgorithm, environment);
+ return CertParsingUtils.trustManager(keyStorePath, keyStoreType, keyStorePassword.getChars(), trustStoreAlgorithm, environment);
} catch (Exception e) {
throw new ElasticsearchException("failed to initialize a TrustManagerFactory", e);
}
@@ -90,8 +90,8 @@ class StoreKeyConfig extends KeyConfig {
@Override
Collection certificates(Environment environment) throws GeneralSecurityException, IOException {
- final Path path = CertUtils.resolvePath(keyStorePath, environment);
- final KeyStore trustStore = CertUtils.readKeyStore(path, keyStoreType, keyStorePassword.getChars());
+ final Path path = CertParsingUtils.resolvePath(keyStorePath, environment);
+ final KeyStore trustStore = CertParsingUtils.readKeyStore(path, keyStoreType, keyStorePassword.getChars());
final List certificates = new ArrayList<>();
final Enumeration aliases = trustStore.aliases();
while (aliases.hasMoreElements()) {
@@ -112,7 +112,7 @@ class StoreKeyConfig extends KeyConfig {
@Override
List filesToMonitor(@Nullable Environment environment) {
- return Collections.singletonList(CertUtils.resolvePath(keyStorePath, environment));
+ return Collections.singletonList(CertParsingUtils.resolvePath(keyStorePath, environment));
}
@Override
@@ -137,7 +137,7 @@ class StoreKeyConfig extends KeyConfig {
private KeyStore getKeyStore(@Nullable Environment environment)
throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
- try (InputStream in = Files.newInputStream(CertUtils.resolvePath(keyStorePath, environment))) {
+ try (InputStream in = Files.newInputStream(CertParsingUtils.resolvePath(keyStorePath, environment))) {
KeyStore ks = KeyStore.getInstance(keyStoreType);
ks.load(in, keyStorePassword.getChars());
return ks;
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreTrustConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreTrustConfig.java
index 9b06249000c..7398d32a61c 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreTrustConfig.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreTrustConfig.java
@@ -55,7 +55,8 @@ class StoreTrustConfig extends TrustConfig {
@Override
X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) {
try {
- return CertUtils.trustManager(trustStorePath, trustStoreType, trustStorePassword.getChars(), trustStoreAlgorithm, environment);
+ return CertParsingUtils.trustManager(trustStorePath, trustStoreType, trustStorePassword.getChars(),
+ trustStoreAlgorithm, environment);
} catch (Exception e) {
throw new ElasticsearchException("failed to initialize a TrustManagerFactory", e);
}
@@ -63,8 +64,8 @@ class StoreTrustConfig extends TrustConfig {
@Override
Collection certificates(Environment environment) throws GeneralSecurityException, IOException {
- final Path path = CertUtils.resolvePath(trustStorePath, environment);
- final KeyStore trustStore = CertUtils.readKeyStore(path, trustStoreType, trustStorePassword.getChars());
+ final Path path = CertParsingUtils.resolvePath(trustStorePath, environment);
+ final KeyStore trustStore = CertParsingUtils.readKeyStore(path, trustStoreType, trustStorePassword.getChars());
final List certificates = new ArrayList<>();
final Enumeration aliases = trustStore.aliases();
while (aliases.hasMoreElements()) {
@@ -83,7 +84,7 @@ class StoreTrustConfig extends TrustConfig {
if (trustStorePath == null) {
return Collections.emptyList();
}
- return Collections.singletonList(CertUtils.resolvePath(trustStorePath, environment));
+ return Collections.singletonList(CertParsingUtils.resolvePath(trustStorePath, environment));
}
@Override
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TrustConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TrustConfig.java
index b6f638f3b69..f7f6d28f176 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TrustConfig.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TrustConfig.java
@@ -79,7 +79,7 @@ abstract class TrustConfig {
}
try {
- return CertUtils.trustManager(trustConfigs.stream()
+ return CertParsingUtils.trustManager(trustConfigs.stream()
.flatMap((tc) -> Arrays.stream(tc.createTrustManager(environment).getAcceptedIssuers()))
.collect(Collectors.toList())
.toArray(new X509Certificate[0]));
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertGenUtilsTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertGenUtilsTests.java
new file mode 100644
index 00000000000..cf6ab53b9f5
--- /dev/null
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertGenUtilsTests.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+package org.elasticsearch.xpack.core.ssl;
+
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.elasticsearch.common.SuppressForbidden;
+import org.elasticsearch.common.network.InetAddresses;
+import org.elasticsearch.common.network.NetworkAddress;
+import org.elasticsearch.test.ESTestCase;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.security.KeyPair;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+/**
+ * Unit tests for cert utils
+ */
+public class CertGenUtilsTests extends ESTestCase {
+
+ public void testSerialNotRepeated() {
+ int iterations = scaledRandomIntBetween(10, 100);
+ List list = new ArrayList<>(iterations);
+ for (int i = 0; i < iterations; i++) {
+ BigInteger serial = CertGenUtils.getSerial();
+ assertThat(list.contains(serial), is(false));
+ list.add(serial);
+ }
+ }
+
+ public void testGenerateKeyPair() throws Exception {
+ KeyPair keyPair = CertGenUtils.generateKeyPair(randomFrom(1024, 2048));
+ assertThat(keyPair.getPrivate().getAlgorithm(), is("RSA"));
+ assertThat(keyPair.getPublic().getAlgorithm(), is("RSA"));
+ }
+
+ public void testSubjectAlternativeNames() throws Exception {
+ final boolean resolveName = randomBoolean();
+ InetAddress address = InetAddresses.forString("127.0.0.1");
+
+ GeneralNames generalNames = CertGenUtils.getSubjectAlternativeNames(resolveName, Collections.singleton(address));
+ assertThat(generalNames, notNullValue());
+ GeneralName[] generalNameArray = generalNames.getNames();
+ assertThat(generalNameArray, notNullValue());
+
+ logger.info("resolve name [{}], address [{}], subject alt names [{}]", resolveName, NetworkAddress.format(address), generalNames);
+ if (resolveName && isResolvable(address)) {
+ assertThat(generalNameArray.length, is(2));
+ int firstType = generalNameArray[0].getTagNo();
+ if (firstType == GeneralName.iPAddress) {
+ assertThat(generalNameArray[1].getTagNo(), is(GeneralName.dNSName));
+ } else if (firstType == GeneralName.dNSName) {
+ assertThat(generalNameArray[1].getTagNo(), is(GeneralName.iPAddress));
+ } else {
+ fail("unknown tag value: " + firstType);
+ }
+ } else {
+ assertThat(generalNameArray.length, is(1));
+ assertThat(generalNameArray[0].getTagNo(), is(GeneralName.iPAddress));
+ }
+ }
+
+ @SuppressForbidden(reason = "need to use getHostName to resolve DNS name and getHostAddress to ensure we resolved the name")
+ private boolean isResolvable(InetAddress inetAddress) {
+ String hostname = inetAddress.getHostName();
+ return hostname.equals(inetAddress.getHostAddress()) == false;
+ }
+
+ public void testIsAnyLocalAddress() throws Exception {
+ InetAddress address = mock(InetAddress.class);
+ when(address.isAnyLocalAddress()).thenReturn(true);
+
+ GeneralNames generalNames = CertGenUtils.getSubjectAlternativeNames(randomBoolean(), Collections.singleton(address));
+ assertThat(generalNames, notNullValue());
+ GeneralName[] generalNameArray = generalNames.getNames();
+ assertThat(generalNameArray, notNullValue());
+
+ verify(address).isAnyLocalAddress();
+ verifyNoMoreInteractions(address);
+ }
+
+}
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertParsingUtilsTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertParsingUtilsTests.java
new file mode 100644
index 00000000000..91891198c17
--- /dev/null
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertParsingUtilsTests.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+package org.elasticsearch.xpack.core.ssl;
+
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.ECPrivateKey;
+import java.util.Collections;
+import java.util.List;
+
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.is;
+
+public class CertParsingUtilsTests extends ESTestCase {
+ public void testReadKeysCorrectly() throws Exception {
+ // read in keystore version
+ Path keystorePath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
+ Key key;
+ try (InputStream in = Files.newInputStream(keystorePath)) {
+ KeyStore keyStore = KeyStore.getInstance("jks");
+ keyStore.load(in, "testnode".toCharArray());
+ key = keyStore.getKey("testnode_RSA", "testnode".toCharArray());
+ }
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"), "testnode"::toCharArray);
+
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadCertsCorrectly() throws Exception {
+ // read in keystore version
+ Path keystorePath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
+ Certificate certificate;
+ try (InputStream in = Files.newInputStream(keystorePath)) {
+ KeyStore keyStore = KeyStore.getInstance("jks");
+ keyStore.load(in, "testnode".toCharArray());
+ certificate = keyStore.getCertificate("testnode_rsa");
+ }
+ assertThat(certificate, notNullValue());
+ assertThat(certificate, instanceOf(X509Certificate.class));
+
+ Certificate pemCert;
+ try (InputStream input =
+ Files.newInputStream(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"))) {
+ List certificateList = CertParsingUtils.readCertificates(input);
+ assertThat(certificateList.size(), is(1));
+ pemCert = certificateList.get(0);
+ }
+ assertThat(pemCert, notNullValue());
+ assertThat(pemCert, equalTo(certificate));
+ }
+
+ public void testReadEllipticCurveCertificateAndKey() throws Exception {
+ Path keyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key.pem");
+ verifyPrime256v1ECKey(keyPath);
+
+ Path keyPkcs8Path = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key-noparam-pkcs8.pem");
+ verifyPrime256v1ECKey(keyPkcs8Path);
+
+ Path keyNoSpecPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key-noparam.pem");
+ verifyPrime256v1ECKey(keyNoSpecPath);
+
+ Path certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-cert.pem");
+ Certificate[] certs = CertParsingUtils.readCertificates(Collections.singletonList(certPath.toString()), null);
+ assertEquals(1, certs.length);
+ Certificate cert = certs[0];
+ assertNotNull(cert);
+ assertEquals("EC", cert.getPublicKey().getAlgorithm());
+ }
+
+ private void verifyPrime256v1ECKey(Path keyPath) {
+ PrivateKey privateKey = PemUtils.readPrivateKey(keyPath, () -> null);
+ assertEquals("EC", privateKey.getAlgorithm());
+ assertThat(privateKey, instanceOf(ECPrivateKey.class));
+ }
+}
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertUtilsTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertUtilsTests.java
deleted file mode 100644
index 07fbee15c57..00000000000
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/CertUtilsTests.java
+++ /dev/null
@@ -1,187 +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;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.core.ssl;
-
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.jce.spec.ECNamedCurveSpec;
-import org.elasticsearch.common.SuppressForbidden;
-import org.elasticsearch.common.network.InetAddresses;
-import org.elasticsearch.common.network.NetworkAddress;
-import org.elasticsearch.test.ESTestCase;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.security.Key;
-import java.security.KeyPair;
-import java.security.KeyStore;
-import java.security.PrivateKey;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.ECPrivateKey;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-/**
- * Unit tests for cert utils
- */
-public class CertUtilsTests extends ESTestCase {
-
- public void testSerialNotRepeated() {
- int iterations = scaledRandomIntBetween(10, 100);
- List list = new ArrayList<>(iterations);
- for (int i = 0; i < iterations; i++) {
- BigInteger serial = CertUtils.getSerial();
- assertThat(list.contains(serial), is(false));
- list.add(serial);
- }
- }
-
- public void testGenerateKeyPair() throws Exception {
- KeyPair keyPair = CertUtils.generateKeyPair(randomFrom(1024, 2048));
- assertThat(keyPair.getPrivate().getAlgorithm(), is("RSA"));
- assertThat(keyPair.getPublic().getAlgorithm(), is("RSA"));
- }
-
- public void testReadKeysCorrectly() throws Exception {
- // read in keystore version
- Path keystorePath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
- Key key;
- try (InputStream in = Files.newInputStream(keystorePath)) {
- KeyStore keyStore = KeyStore.getInstance("jks");
- keyStore.load(in, "testnode".toCharArray());
- key = keyStore.getKey("testnode", "testnode".toCharArray());
- }
- assertThat(key, notNullValue());
- assertThat(key, instanceOf(PrivateKey.class));
-
- PrivateKey privateKey;
- try (Reader reader =
- Files.newBufferedReader(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"),
- StandardCharsets.UTF_8)) {
- privateKey = CertUtils.readPrivateKey(reader, "testnode"::toCharArray);
- }
- assertThat(privateKey, notNullValue());
- assertThat(privateKey, equalTo(key));
- }
-
- public void testReadCertsCorrectly() throws Exception {
- // read in keystore version
- Path keystorePath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
- Certificate certificate;
- try (InputStream in = Files.newInputStream(keystorePath)) {
- KeyStore keyStore = KeyStore.getInstance("jks");
- keyStore.load(in, "testnode".toCharArray());
- certificate = keyStore.getCertificate("testnode");
- }
- assertThat(certificate, notNullValue());
- assertThat(certificate, instanceOf(X509Certificate.class));
-
- Certificate pemCert;
- try (Reader reader =
- Files.newBufferedReader(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"),
- StandardCharsets.UTF_8)) {
- List certificateList = new ArrayList<>(1);
- CertUtils.readCertificates(reader, certificateList, CertificateFactory.getInstance("X.509"));
- assertThat(certificateList.size(), is(1));
- pemCert = certificateList.get(0);
- }
- assertThat(pemCert, notNullValue());
- assertThat(pemCert, equalTo(certificate));
- }
-
- public void testSubjectAlternativeNames() throws Exception {
- final boolean resolveName = randomBoolean();
- InetAddress address = InetAddresses.forString("127.0.0.1");
-
- GeneralNames generalNames = CertUtils.getSubjectAlternativeNames(resolveName, Collections.singleton(address));
- assertThat(generalNames, notNullValue());
- GeneralName[] generalNameArray = generalNames.getNames();
- assertThat(generalNameArray, notNullValue());
-
- logger.info("resolve name [{}], address [{}], subject alt names [{}]", resolveName, NetworkAddress.format(address), generalNames);
- if (resolveName && isResolvable(address)) {
- assertThat(generalNameArray.length, is(2));
- int firstType = generalNameArray[0].getTagNo();
- if (firstType == GeneralName.iPAddress) {
- assertThat(generalNameArray[1].getTagNo(), is(GeneralName.dNSName));
- } else if (firstType == GeneralName.dNSName) {
- assertThat(generalNameArray[1].getTagNo(), is(GeneralName.iPAddress));
- } else {
- fail("unknown tag value: " + firstType);
- }
- } else {
- assertThat(generalNameArray.length, is(1));
- assertThat(generalNameArray[0].getTagNo(), is(GeneralName.iPAddress));
- }
- }
-
- @SuppressForbidden(reason = "need to use getHostName to resolve DNS name and getHostAddress to ensure we resolved the name")
- private boolean isResolvable(InetAddress inetAddress) {
- String hostname = inetAddress.getHostName();
- return hostname.equals(inetAddress.getHostAddress()) == false;
- }
-
- public void testIsAnyLocalAddress() throws Exception {
- InetAddress address = mock(InetAddress.class);
- when(address.isAnyLocalAddress()).thenReturn(true);
-
- GeneralNames generalNames = CertUtils.getSubjectAlternativeNames(randomBoolean(), Collections.singleton(address));
- assertThat(generalNames, notNullValue());
- GeneralName[] generalNameArray = generalNames.getNames();
- assertThat(generalNameArray, notNullValue());
-
- verify(address).isAnyLocalAddress();
- verifyNoMoreInteractions(address);
- }
-
- public void testReadEllipticCurveCertificateAndKey() throws Exception {
- Path keyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key.pem");
- try (Reader reader = Files.newBufferedReader(keyPath)) {
- verifyPrime256v1ECKey(reader);
- }
-
- Path keyNoSpecPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key-noparam.pem");
- try (Reader reader = Files.newBufferedReader(keyNoSpecPath)) {
- verifyPrime256v1ECKey(reader);
- }
-
- Path certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-cert.pem");
- Certificate[] certs = CertUtils.readCertificates(Collections.singletonList(certPath.toString()), null);
- assertEquals(1, certs.length);
- Certificate cert = certs[0];
- assertNotNull(cert);
- assertEquals("EC", cert.getPublicKey().getAlgorithm());
- }
-
- private void verifyPrime256v1ECKey(Reader reader) throws Exception {
- PrivateKey privateKey = CertUtils.readPrivateKey(reader, () -> null);
- assertNotNull(privateKey);
- assertEquals("ECDSA", privateKey.getAlgorithm());
- assertThat(privateKey, instanceOf(ECPrivateKey.class));
- ECPrivateKey ecPrivateKey = (ECPrivateKey) privateKey;
- assertThat(ecPrivateKey.getParams(), instanceOf(ECNamedCurveSpec.class));
- ECNamedCurveSpec namedCurveSpec = (ECNamedCurveSpec) ecPrivateKey.getParams();
- assertEquals("prime256v1", namedCurveSpec.getName());
- }
-
-}
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/PemUtilsTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/PemUtilsTests.java
new file mode 100644
index 00000000000..880cb03a64f
--- /dev/null
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/PemUtilsTests.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+package org.elasticsearch.xpack.core.ssl;
+
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.core.StringContains.containsString;
+
+public class PemUtilsTests extends ESTestCase {
+
+ public void testReadPKCS8RsaKey() throws Exception {
+ Key key = getKeyFromKeystore("RSA");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/rsa_key_pkcs8_plain.pem"), ""::toCharArray);
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadPKCS8DsaKey() throws Exception {
+ Key key = getKeyFromKeystore("DSA");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_pkcs8_plain.pem"), ""::toCharArray);
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadPKCS8EcKey() throws Exception {
+ Key key = getKeyFromKeystore("EC");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_pkcs8_plain.pem"), ""::toCharArray);
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadEncryptedPKCS8Key() throws Exception {
+ Key key = getKeyFromKeystore("RSA");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/key_pkcs8_encrypted" +
+ ".pem"), "testnode"::toCharArray);
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadDESEncryptedPKCS1Key() throws Exception {
+ Key key = getKeyFromKeystore("RSA");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"), "testnode"::toCharArray);
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadAESEncryptedPKCS1Key() throws Exception {
+ Key key = getKeyFromKeystore("RSA");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ String bits = randomFrom("128", "192", "256");
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes" + bits + ".pem"),
+ "testnode"::toCharArray);
+
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadPKCS1RsaKey() throws Exception {
+ Key key = getKeyFromKeystore("RSA");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-unprotected.pem"),
+ "testnode"::toCharArray);
+
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadOpenSslDsaKey() throws Exception {
+ Key key = getKeyFromKeystore("DSA");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_plain.pem"),
+ ""::toCharArray);
+
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadOpenSslDsaKeyWithParams() throws Exception {
+ Key key = getKeyFromKeystore("DSA");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_plain_with_params.pem"),
+ ""::toCharArray);
+
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadEncryptedOpenSslDsaKey() throws Exception {
+ Key key = getKeyFromKeystore("DSA");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_encrypted.pem"),
+ "testnode"::toCharArray);
+
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadOpenSslEcKey() throws Exception {
+ Key key = getKeyFromKeystore("EC");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_plain.pem"),
+ ""::toCharArray);
+
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadOpenSslEcKeyWithParams() throws Exception {
+ Key key = getKeyFromKeystore("EC");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_plain_with_params.pem"),
+ ""::toCharArray);
+
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadEncryptedOpenSslEcKey() throws Exception {
+ Key key = getKeyFromKeystore("EC");
+ assertThat(key, notNullValue());
+ assertThat(key, instanceOf(PrivateKey.class));
+ PrivateKey privateKey = PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_encrypted.pem"),
+ "testnode"::toCharArray);
+
+ assertThat(privateKey, notNullValue());
+ assertThat(privateKey, equalTo(key));
+ }
+
+ public void testReadUnsupportedKey() {
+ IllegalStateException e = expectThrows(IllegalStateException.class, () -> PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/key_unsupported.pem"),
+ "testnode"::toCharArray));
+ assertThat(e.getMessage(), containsString("File did not contain a supported key format"));
+ }
+
+ public void testReadUnsupportedPemFile() {
+ IllegalStateException e = expectThrows(IllegalStateException.class, () -> PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"),
+ "testnode"::toCharArray));
+ assertThat(e.getMessage(), containsString("File did not contain a supported key format"));
+ }
+
+ public void testReadCorruptedKey() {
+ IllegalStateException e = expectThrows(IllegalStateException.class, () -> PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/corrupted_key_pkcs8_plain.pem"),
+ "testnode"::toCharArray));
+ assertThat(e.getMessage(), containsString("Error parsing Private Key from"));
+ assertThat(e.getCause().getMessage(), containsString("Malformed PEM file, PEM footer is invalid or missing"));
+ }
+
+ public void testReadEmptyFile() {
+ IllegalStateException e = expectThrows(IllegalStateException.class, () -> PemUtils.readPrivateKey(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/empty.pem"),
+ "testnode"::toCharArray));
+ assertThat(e.getMessage(), containsString("File is empty"));
+ }
+
+ private Key getKeyFromKeystore(String algo) throws Exception {
+ Path keystorePath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
+ try (InputStream in = Files.newInputStream(keystorePath)) {
+ KeyStore keyStore = KeyStore.getInstance("jks");
+ keyStore.load(in, "testnode".toCharArray());
+ return keyStore.getKey("testnode_" + algo, "testnode".toCharArray());
+ }
+ }
+}
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManagerTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManagerTests.java
index 560459956cb..c1a39582e4f 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManagerTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManagerTests.java
@@ -5,21 +5,21 @@
*/
package org.elasticsearch.xpack.core.ssl;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.operator.OperatorException;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESTestCase;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Assert;
import org.junit.Before;
-
import javax.net.ssl.X509ExtendedTrustManager;
-import javax.security.auth.x500.X500Principal;
import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
import java.security.GeneralSecurityException;
-import java.security.KeyPair;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@@ -33,44 +33,59 @@ import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import static org.elasticsearch.xpack.core.ssl.CertUtils.generateSignedCertificate;
-
public class RestrictedTrustManagerTests extends ESTestCase {
- /**
- * Use a small keysize for performance, since the keys are only used in this test, but a large enough keysize
- * to get past the SSL algorithm checker
- */
- private static final int KEYSIZE = 1024;
-
private X509ExtendedTrustManager baseTrustManager;
private Map certificates;
private int numberOfClusters;
private int numberOfNodes;
@Before
- public void generateCertificates() throws GeneralSecurityException, IOException, OperatorException {
- KeyPair caPair = CertUtils.generateKeyPair(KEYSIZE);
- X500Principal ca = new X500Principal("cn=CertAuth");
- X509Certificate caCert = CertUtils.generateCACertificate(ca, caPair, 30);
- baseTrustManager = CertUtils.trustManager(new Certificate[] { caCert });
+ public void readCertificates() throws GeneralSecurityException, IOException {
+ Certificate[] caCert
+ = CertParsingUtils.readCertificates(Collections.singletonList(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca.crt")));
+ baseTrustManager = CertParsingUtils.trustManager(caCert);
certificates = new HashMap<>();
+ Files.walkFileTree(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed"), new SimpleFileVisitor() {
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ try {
+ String fileName = file.getFileName().toString();
+ if (fileName.endsWith(".crt")) {
+ certificates.put(fileName.replace(".crt", "/self"), CertParsingUtils
+ .readX509Certificates(Collections.singletonList(file)));
+ }
+ return FileVisitResult.CONTINUE;
+ } catch (CertificateException e) {
+ throw new IOException("Failed to read X.509 Certificate from: " + file.toAbsolutePath().toString());
+ }
+ }
+ });
+
+ Files.walkFileTree(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed"), new SimpleFileVisitor() {
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ try {
+ String fileName = file.getFileName().toString();
+ if (fileName.endsWith(".crt")) {
+ certificates.put(fileName.replace(".crt", "/ca"), CertParsingUtils
+ .readX509Certificates(Collections.singletonList(file)));
+ }
+ return FileVisitResult.CONTINUE;
+ } catch (CertificateException e) {
+ throw new IOException("Failed to read X.509 Certificate from: " + file.toAbsolutePath().toString());
+ }
+ }
+ });
+
numberOfClusters = scaledRandomIntBetween(2, 8);
numberOfNodes = scaledRandomIntBetween(2, 8);
- for (int cluster = 1; cluster <= numberOfClusters; cluster++) {
- for (int node = 1; node <= numberOfNodes; node++) {
- KeyPair nodePair = CertUtils.generateKeyPair(KEYSIZE);
- final String cn = "n" + node + ".c" + cluster;
- final X500Principal principal = new X500Principal("cn=" + cn);
- final String san = "node" + node + ".cluster" + cluster + ".elasticsearch";
- final GeneralNames altNames = new GeneralNames(CertUtils.createCommonName(san));
- final X509Certificate signed = generateSignedCertificate(principal, altNames, nodePair, caCert, caPair.getPrivate(), 30);
- final X509Certificate self = generateSignedCertificate(principal, altNames, nodePair, null, null, 30);
- certificates.put(cn + "/ca", new X509Certificate[] { signed });
- certificates.put(cn + "/self", new X509Certificate[] { self });
- }
- }
}
public void testTrustsExplicitCertificateName() throws Exception {
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java
index 2ccbd549105..63a5be61043 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java
@@ -9,8 +9,6 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
-import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
-import org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder;
import org.elasticsearch.common.CheckedRunnable;
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.Settings;
@@ -27,14 +25,10 @@ import org.junit.Before;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
-import javax.security.auth.x500.X500Principal;
-import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -42,16 +36,13 @@ import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.security.AccessController;
import java.security.KeyManagementException;
-import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.UnrecoverableKeyException;
-import java.security.cert.Certificate;
import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
@@ -87,14 +78,16 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
public void testReloadingKeyStore() throws Exception {
final Path tempDir = createTempDir();
final Path keystorePath = tempDir.resolve("testnode.jks");
+ final Path updatedKeystorePath = tempDir.resolve("testnode_updated.jks");
Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"), keystorePath);
+ Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.jks"), updatedKeystorePath);
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
final Settings settings = Settings.builder()
- .put("path.home", createTempDir())
- .put("xpack.ssl.keystore.path", keystorePath)
- .setSecureSettings(secureSettings)
- .build();
+ .put("path.home", createTempDir())
+ .put("xpack.ssl.keystore.path", keystorePath)
+ .setSecureSettings(secureSettings)
+ .build();
final Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings);
//Load HTTPClient only once. Client uses the same store as a truststore
try (CloseableHttpClient client = getSSLClient(keystorePath, "testnode")) {
@@ -110,22 +103,12 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
final Runnable modifier = () -> {
try {
- // modify the keystore that the KeyManager uses
- KeyStore keyStore = KeyStore.getInstance("jks");
- keyStore.load(null, null);
- final KeyPair keyPair = CertUtils.generateKeyPair(512);
- X509Certificate cert = CertUtils.generateSignedCertificate(new X500Principal("CN=localhost"), null, keyPair,
- null, null, 365);
- keyStore.setKeyEntry("key", keyPair.getPrivate(), "testnode".toCharArray(), new X509Certificate[]{cert});
- Path updated = tempDir.resolve("updated.jks");
- try (OutputStream out = Files.newOutputStream(updated)) {
- keyStore.store(out, "testnode".toCharArray());
- }
- atomicMoveIfPossible(updated, keystorePath);
+ atomicMoveIfPossible(updatedKeystorePath, keystorePath);
} catch (Exception e) {
throw new RuntimeException("modification failed", e);
}
};
+
// The new server certificate is not in the client's truststore so SSLHandshake should fail
final Consumer keyMaterialPostChecks = (updatedContext) -> {
try (MockWebServer server = new MockWebServer(updatedContext, true)) {
@@ -133,7 +116,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
server.start();
SSLHandshakeException sslException = expectThrows(SSLHandshakeException.class, () ->
privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close()));
- assertThat(sslException.getCause().getMessage(), containsString("PKIX path building failed"));
+ assertThat(sslException.getCause().getMessage(), containsString("PKIX path validation failed"));
} catch (Exception e) {
throw new RuntimeException("Exception starting or connecting to the mock server", e);
}
@@ -141,18 +124,21 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
validateSSLConfigurationIsReloaded(settings, env, keyMaterialPreChecks, modifier, keyMaterialPostChecks);
}
}
-
/**
* Tests the reloading of SSLContext when a PEM key and certificate are used.
*/
- public void testPEMKeyCertConfigReloading() throws Exception {
- final Path tempDir = createTempDir();
- final Path keyPath = tempDir.resolve("testnode.pem");
- final Path certPath = tempDir.resolve("testnode.crt");
+ public void testPEMKeyConfigReloading() throws Exception {
+ Path tempDir = createTempDir();
+ Path keyPath = tempDir.resolve("testnode.pem");
+ Path updatedKeyPath = tempDir.resolve("testnode_updated.pem");
+ Path certPath = tempDir.resolve("testnode.crt");
+ Path updatedCertPath = tempDir.resolve("testnode_updated.crt");
final Path clientTruststorePath = tempDir.resolve("testnode.jks");
- Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"), clientTruststorePath);
Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"), keyPath);
+ Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.pem"), updatedKeyPath);
+ Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt"), updatedCertPath);
Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"), certPath);
+ Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"), clientTruststorePath);
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("xpack.ssl.secure_key_passphrase", "testnode");
final Settings settings = Settings.builder()
@@ -176,27 +162,13 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
};
final Runnable modifier = () -> {
try {
- final KeyPair keyPair = CertUtils.generateKeyPair(512);
- X509Certificate cert = CertUtils.generateSignedCertificate(new X500Principal("CN=localhost"), null, keyPair,
- null, null, 365);
- Path updatedKeyPath = tempDir.resolve("updated.pem");
- Path updatedCertPath = tempDir.resolve("updated.crt");
- try (OutputStream os = Files.newOutputStream(updatedKeyPath);
- OutputStreamWriter osWriter = new OutputStreamWriter(os, StandardCharsets.UTF_8);
- JcaPEMWriter writer = new JcaPEMWriter(osWriter)) {
- writer.writeObject(keyPair,
- new JcePEMEncryptorBuilder("DES-EDE3-CBC").setProvider(CertUtils.BC_PROV).build("testnode".toCharArray()));
- }
- try (BufferedWriter out = Files.newBufferedWriter(updatedCertPath);
- JcaPEMWriter pemWriter = new JcaPEMWriter(out)) {
- pemWriter.writeObject(cert);
- }
atomicMoveIfPossible(updatedKeyPath, keyPath);
atomicMoveIfPossible(updatedCertPath, certPath);
} catch (Exception e) {
throw new RuntimeException("failed to modify file", e);
}
};
+
// The new server certificate is not in the client's truststore so SSLHandshake should fail
final Consumer keyMaterialPostChecks = (updatedContext) -> {
try (MockWebServer server = new MockWebServer(updatedContext, false)) {
@@ -204,12 +176,11 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
server.start();
SSLHandshakeException sslException = expectThrows(SSLHandshakeException.class, () ->
privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close()));
- assertThat(sslException.getCause().getMessage(), containsString("PKIX path building failed"));
+ assertThat(sslException.getCause().getMessage(), containsString("PKIX path validation failed"));
} catch (Exception e) {
throw new RuntimeException("Exception starting or connecting to the mock server", e);
}
};
-
validateSSLConfigurationIsReloaded(settings, env, keyMaterialPreChecks, modifier, keyMaterialPostChecks);
}
}
@@ -221,7 +192,9 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
public void testReloadingTrustStore() throws Exception {
Path tempDir = createTempDir();
Path trustStorePath = tempDir.resolve("testnode.jks");
+ Path updatedTruststorePath = tempDir.resolve("testnode_updated.jks");
Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"), trustStorePath);
+ Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.jks"), updatedTruststorePath);
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("xpack.ssl.truststore.secure_password", "testnode");
Settings settings = Settings.builder()
@@ -231,9 +204,9 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
.build();
Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings);
// Create the MockWebServer once for both pre and post checks
- try(MockWebServer server = getSslServer(trustStorePath, "testnode")){
+ try (MockWebServer server = getSslServer(trustStorePath, "testnode")) {
final Consumer trustMaterialPreChecks = (context) -> {
- try (CloseableHttpClient client = HttpClients.custom().setSSLContext(context).build()){
+ try (CloseableHttpClient client = HttpClients.custom().setSSLContext(context).build()) {
privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close());
} catch (Exception e) {
throw new RuntimeException("Error connecting to the mock server", e);
@@ -242,17 +215,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
final Runnable modifier = () -> {
try {
- Path updatedTrustStore = tempDir.resolve("updated.jks");
- KeyStore keyStore = KeyStore.getInstance("jks");
- keyStore.load(null, null);
- final KeyPair keyPair = CertUtils.generateKeyPair(512);
- X509Certificate cert = CertUtils.generateSignedCertificate(new X500Principal("CN=localhost"), null, keyPair,
- null, null, 365);
- keyStore.setKeyEntry("newKey", keyPair.getPrivate(), "testnode".toCharArray(), new Certificate[]{cert});
- try (OutputStream out = Files.newOutputStream(updatedTrustStore)) {
- keyStore.store(out, "testnode".toCharArray());
- }
- atomicMoveIfPossible(updatedTrustStore, trustStorePath);
+ atomicMoveIfPossible(updatedTruststorePath, trustStorePath);
} catch (Exception e) {
throw new RuntimeException("failed to modify file", e);
}
@@ -260,7 +223,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
// Client's truststore doesn't contain the server's certificate anymore so SSLHandshake should fail
final Consumer trustMaterialPostChecks = (updatedContext) -> {
- try (CloseableHttpClient client = HttpClients.custom().setSSLContext(updatedContext).build()){
+ try (CloseableHttpClient client = HttpClients.custom().setSSLContext(updatedContext).build()) {
SSLHandshakeException sslException = expectThrows(SSLHandshakeException.class, () ->
privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close()));
assertThat(sslException.getCause().getMessage(), containsString("PKIX path building failed"));
@@ -268,11 +231,9 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
throw new RuntimeException("Error closing CloseableHttpClient", e);
}
};
-
validateSSLConfigurationIsReloaded(settings, env, trustMaterialPreChecks, modifier, trustMaterialPostChecks);
}
}
-
/**
* Test the reloading of SSLContext whose trust config is backed by PEM certificate files.
*/
@@ -281,16 +242,18 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
Path clientCertPath = tempDir.resolve("testnode.crt");
Path keyStorePath = tempDir.resolve("testnode.jks");
Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"), keyStorePath);
- Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"), clientCertPath);
+ //Our keystore contains two Certificates it can present. One build from the RSA keypair and one build from the EC keypair. EC is
+ // used since it keyManager presents the first one in alias alphabetical order (and testnode_ec comes before testnode_rsa)
+ Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt"), clientCertPath);
Settings settings = Settings.builder()
- .putList("xpack.ssl.certificate_authorities", clientCertPath.toString())
+ .putList("xpack.ssl.certificate_authorities", clientCertPath.toString())
.put("path.home", createTempDir())
.build();
Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings);
// Create the MockWebServer once for both pre and post checks
- try(MockWebServer server = getSslServer(keyStorePath, "testnode")){
+ try (MockWebServer server = getSslServer(keyStorePath, "testnode")) {
final Consumer trustMaterialPreChecks = (context) -> {
- try (CloseableHttpClient client = HttpClients.custom().setSSLContext(context).build()){
+ try (CloseableHttpClient client = HttpClients.custom().setSSLContext(context).build()) {
privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close());
} catch (Exception e) {
throw new RuntimeException("Exception connecting to the mock server", e);
@@ -299,22 +262,18 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
final Runnable modifier = () -> {
try {
- final KeyPair keyPair = CertUtils.generateKeyPair(512);
- X509Certificate cert = CertUtils.generateSignedCertificate(new X500Principal("CN=localhost"), null, keyPair,
- null, null, 365);
- Path updatedCertPath = tempDir.resolve("updated.crt");
- try (BufferedWriter out = Files.newBufferedWriter(updatedCertPath);
- JcaPEMWriter pemWriter = new JcaPEMWriter(out)) {
- pemWriter.writeObject(cert);
- }
- atomicMoveIfPossible(updatedCertPath, clientCertPath);
+ Path updatedCert = tempDir.resolve("updated.crt");
+ Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt"),
+ updatedCert, StandardCopyOption.REPLACE_EXISTING);
+ atomicMoveIfPossible(updatedCert, clientCertPath);
} catch (Exception e) {
throw new RuntimeException("failed to modify file", e);
}
};
+
// Client doesn't trust the Server certificate anymore so SSLHandshake should fail
final Consumer trustMaterialPostChecks = (updatedContext) -> {
- try (CloseableHttpClient client = HttpClients.custom().setSSLContext(updatedContext).build()){
+ try (CloseableHttpClient client = HttpClients.custom().setSSLContext(updatedContext).build()) {
SSLHandshakeException sslException = expectThrows(SSLHandshakeException.class, () ->
privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close()));
assertThat(sslException.getCause().getMessage(), containsString("PKIX path building failed"));
@@ -322,7 +281,6 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
throw new RuntimeException("Error closing CloseableHttpClient", e);
}
};
-
validateSSLConfigurationIsReloaded(settings, env, trustMaterialPreChecks, modifier, trustMaterialPostChecks);
}
}
@@ -447,9 +405,9 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
Path clientCertPath = tempDir.resolve("testclient.crt");
Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.crt"), clientCertPath);
Settings settings = Settings.builder()
- .putList("xpack.ssl.certificate_authorities", clientCertPath.toString())
- .put("path.home", createTempDir())
- .build();
+ .putList("xpack.ssl.certificate_authorities", clientCertPath.toString())
+ .put("path.home", createTempDir())
+ .build();
Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings);
final SSLService sslService = new SSLService(settings, env);
final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY);
@@ -471,13 +429,13 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
// we intentionally don't wait here as we rely on concurrency to catch a failure
assertThat(sslService.sslContextHolder(config).sslContext(), sameInstance(context));
- }
+ }
private void validateSSLConfigurationIsReloaded(Settings settings, Environment env,
Consumer preChecks,
Runnable modificationFunction,
Consumer postChecks)
- throws Exception {
+ throws Exception {
final CountDownLatch reloadLatch = new CountDownLatch(1);
final SSLService sslService = new SSLService(settings, env);
@@ -512,7 +470,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
private static MockWebServer getSslServer(Path keyStorePath, String keyStorePass) throws KeyStoreException, CertificateException,
NoSuchAlgorithmException, IOException, KeyManagementException, UnrecoverableKeyException {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
- try(InputStream is = Files.newInputStream(keyStorePath)) {
+ try (InputStream is = Files.newInputStream(keyStorePath)) {
keyStore.load(is, keyStorePass.toCharArray());
}
final SSLContext sslContext = new SSLContextBuilder().loadKeyMaterial(keyStore, keyStorePass.toCharArray())
@@ -527,7 +485,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
NoSuchAlgorithmException,
KeyManagementException, IOException, CertificateException {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
- try(InputStream is = Files.newInputStream(trustStorePath)) {
+ try (InputStream is = Files.newInputStream(trustStorePath)) {
trustStore.load(is, trustStorePass.toCharArray());
}
final SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(trustStore, null).build();
@@ -544,5 +502,4 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
throw (Exception) e.getCause();
}
}
-
}
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java
index bcb4b638654..727a2b52999 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java
@@ -478,7 +478,7 @@ public class SSLServiceTests extends ESTestCase {
final SSLService sslService = new SSLService(settings, env);
final List certificates = new ArrayList<>(sslService.getLoadedCertificates());
- assertThat(certificates, iterableWithSize(8));
+ assertThat(certificates, iterableWithSize(10));
Collections.sort(certificates,
Comparator.comparing((CertificateInfo c) -> c.alias() == null ? "" : c.alias()).thenComparing(CertificateInfo::path));
@@ -528,24 +528,6 @@ public class SSLServiceTests extends ESTestCase {
assertThat(cert.expiry(), equalTo(DateTime.parse("2019-09-22T18:52:55Z")));
assertThat(cert.hasPrivateKey(), equalTo(false));
- cert = iterator.next();
- assertThat(cert.alias(), equalTo("testnode"));
- assertThat(cert.path(), equalTo(jksPath.toString()));
- assertThat(cert.format(), equalTo("jks"));
- assertThat(cert.serialNumber(), equalTo("b8b96c37e332cccb"));
- assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node, OU=elasticsearch, O=org"));
- assertThat(cert.expiry(), equalTo(DateTime.parse("2019-09-22T18:52:57Z")));
- assertThat(cert.hasPrivateKey(), equalTo(true));
-
- cert = iterator.next();
- assertThat(cert.alias(), equalTo("testnode"));
- assertThat(cert.path(), equalTo(p12Path.toString()));
- assertThat(cert.format(), equalTo("PKCS12"));
- assertThat(cert.serialNumber(), equalTo("b8b96c37e332cccb"));
- assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node, OU=elasticsearch, O=org"));
- assertThat(cert.expiry(), equalTo(DateTime.parse("2019-09-22T18:52:57Z")));
- assertThat(cert.hasPrivateKey(), equalTo(true));
-
cert = iterator.next();
assertThat(cert.alias(), equalTo("testnode-client-profile"));
assertThat(cert.path(), equalTo(jksPath.toString()));
@@ -555,6 +537,42 @@ public class SSLServiceTests extends ESTestCase {
assertThat(cert.expiry(), equalTo(DateTime.parse("2019-09-22T18:52:56Z")));
assertThat(cert.hasPrivateKey(), equalTo(false));
+ cert = iterator.next();
+ assertThat(cert.alias(), equalTo("testnode_dsa"));
+ assertThat(cert.path(), equalTo(jksPath.toString()));
+ assertThat(cert.format(), equalTo("jks"));
+ assertThat(cert.serialNumber(), equalTo("223c736a"));
+ assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node"));
+ assertThat(cert.expiry(), equalTo(DateTime.parse("2045-10-02T09:43:18.000Z")));
+ assertThat(cert.hasPrivateKey(), equalTo(true));
+
+ cert = iterator.next();
+ assertThat(cert.alias(), equalTo("testnode_ec"));
+ assertThat(cert.path(), equalTo(jksPath.toString()));
+ assertThat(cert.format(), equalTo("jks"));
+ assertThat(cert.serialNumber(), equalTo("7268203b"));
+ assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node"));
+ assertThat(cert.expiry(), equalTo(DateTime.parse("2045-10-02T09:36:10.000Z")));
+ assertThat(cert.hasPrivateKey(), equalTo(true));
+
+ cert = iterator.next();
+ assertThat(cert.alias(), equalTo("testnode_rsa"));
+ assertThat(cert.path(), equalTo(jksPath.toString()));
+ assertThat(cert.format(), equalTo("jks"));
+ assertThat(cert.serialNumber(), equalTo("b8b96c37e332cccb"));
+ assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node, OU=elasticsearch, O=org"));
+ assertThat(cert.expiry(), equalTo(DateTime.parse("2019-09-22T18:52:57.000Z")));
+ assertThat(cert.hasPrivateKey(), equalTo(true));
+
+ cert = iterator.next();
+ assertThat(cert.alias(), equalTo("testnode_rsa"));
+ assertThat(cert.path(), equalTo(p12Path.toString()));
+ assertThat(cert.format(), equalTo("PKCS12"));
+ assertThat(cert.serialNumber(), equalTo("b8b96c37e332cccb"));
+ assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node, OU=elasticsearch, O=org"));
+ assertThat(cert.expiry(), equalTo(DateTime.parse("2019-09-22T18:52:57Z")));
+ assertThat(cert.hasPrivateKey(), equalTo(true));
+
assertFalse(iterator.hasNext());
}
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfigTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfigTests.java
index 7c336299881..6dd9bb2b46e 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfigTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfigTests.java
@@ -36,7 +36,7 @@ public class StoreKeyConfigTests extends ESTestCase {
final StoreKeyConfig keyConfig = new StoreKeyConfig(path, type, keyStorePassword, keyStorePassword,
KeyManagerFactory.getDefaultAlgorithm(), TrustManagerFactory.getDefaultAlgorithm());
final X509ExtendedKeyManager keyManager = keyConfig.createKeyManager(TestEnvironment.newEnvironment(settings));
- final PrivateKey key = keyManager.getPrivateKey("testnode");
+ final PrivateKey key = keyManager.getPrivateKey("testnode_rsa");
assertThat(key, notNullValue());
assertThat(key.getAlgorithm(), equalTo("RSA"));
assertThat(key.getFormat(), equalTo("PKCS#8"));
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TestsSSLService.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TestsSSLService.java
index 675e115e4cb..1d1dfe222c7 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TestsSSLService.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TestsSSLService.java
@@ -5,26 +5,17 @@
*/
package org.elasticsearch.xpack.core.ssl;
-import org.bouncycastle.operator.OperatorCreationException;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import javax.net.ssl.SSLContext;
-import javax.security.auth.DestroyFailedException;
-
-import java.io.IOException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
/**
* Extending SSLService to make helper methods public to access in tests
*/
public class TestsSSLService extends SSLService {
- public TestsSSLService(Settings settings, Environment environment) throws CertificateException, UnrecoverableKeyException,
- NoSuchAlgorithmException, IOException, DestroyFailedException, KeyStoreException, OperatorCreationException {
+ public TestsSSLService(Settings settings, Environment environment) {
super(settings, environment);
}
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/cert/CertificateInfoTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/cert/CertificateInfoTests.java
index 77f3c4ea267..5435df5d736 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/cert/CertificateInfoTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/cert/CertificateInfoTests.java
@@ -5,28 +5,23 @@
*/
package org.elasticsearch.xpack.core.ssl.cert;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.test.ESTestCase;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
-import javax.security.auth.x500.X500Principal;
import java.io.IOException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
+import java.util.Collections;
import static org.hamcrest.Matchers.equalTo;
public class CertificateInfoTests extends ESTestCase {
public void testSerialization() throws Exception {
- final X500Principal principal = new X500Principal("CN=foo");
- final X509Certificate certificate = CertUtils.generateSignedCertificate(principal, new GeneralNames(new GeneralName[0]),
- getKeyPair(), null, null, 90);
+ final X509Certificate certificate = CertParsingUtils.
+ readX509Certificates(Collections.singletonList(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")))[0];
final CertificateInfo cert1 = new CertificateInfo("/path/to/cert.jks", "jks", "key", true, certificate);
final CertificateInfo cert2 = serializeAndDeserialize(cert1);
final CertificateInfo cert3 = serializeAndDeserialize(cert2);
@@ -40,11 +35,4 @@ public class CertificateInfoTests extends ESTestCase {
cert1.writeTo(output);
return new CertificateInfo(output.bytes().streamInput());
}
-
- private KeyPair getKeyPair() throws NoSuchAlgorithmException {
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
- keyPairGenerator.initialize(2048);
- return keyPairGenerator.generateKeyPair();
- }
-
}
\ No newline at end of file
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/README.asciidoc b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/README.asciidoc
index 5b2a6b737d7..0136e967106 100644
--- a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/README.asciidoc
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/README.asciidoc
@@ -34,3 +34,116 @@ keytool -importkeystore -destkeystore .jks -srckeystore .p12 -srcsto
The keystore is now created and has the private/public key pair. You can import additional trusted certificates using
`keytool -importcert`. When doing so make sure to specify an alias so that others can recreate the keystore if necessary.
+
+=== Changes and additions for removing Bouncy Castle Dependency
+
+`testnode-unprotected.pem` is simply the decrypted `testnode.pem`
+------
+openssl rsa -in testnode.pem -out testnode-unprotected.pem
+------
+
+`rsa_key_pkcs8_plain.pem` is the same plaintext key encoded in `PKCS#8`
+------
+openssl pkcs8 -topk8 -inform PEM -outform PEM -in testnode-unprotected.pem -out rsa_key_pkcs8_plain.pem -nocrypt
+------
+
+`testnode-aes{128,192,256}.pem` is the testnode.pem private key, encrypted with `AES-128`, `AES-192` and `AES-256`
+respectively, encoded in `PKCS#1`
+[source,shell]
+------
+openssl rsa -aes128 -in testnode-unprotected.pem -out testnode-aes128.pem
+------
+[source,shell]
+------
+openssl rsa -aes192 -in testnode-unprotected.pem -out testnode-aes192.pem
+------
+[source,shell]
+------
+openssl rsa -aes256 -in testnode-unprotected.pem -out testnode-aes256.pem
+------
+
+Adding `DSA` and `EC` Keys to the Keystore
+
+[source,shell]
+------
+keytool -genkeypair -keyalg DSA -alias testnode_dsa -keystore testnode.jks -storepass testnode \
+ -keypass testnode -validity 10000 -keysize 1024 -dname "CN=Elasticsearch Test Node" \
+ -ext SAN=dns:localhost,dns:localhost.localdomain,dns:localhost4,dns:localhost4.localdomain4,dns:localhost6,dns:localhost6.localdomain6,ip:127.0.0.1,ip:0:0:0:0:0:0:0:1
+------
+[source,shell]
+------
+keytool -genkeypair -keyalg EC -alias testnode_ec -keystore testnode.jks -storepass testnode \
+ -keypass testnode -validity 10000 -keysize 256 -dname "CN=Elasticsearch Test Node" \
+ -ext SAN=dns:localhost,dns:localhost.localdomain,dns:localhost4,dns:localhost4.localdomain4,dns:localhost6,dns:localhost6.localdomain6,ip:127.0.0.1,ip:0:0:0:0:0:0:0:1
+------
+
+Exporting the `DSA` and `EC` private keys from the keystore
+
+[source,shell]
+----
+keytool -importkeystore -srckeystore testnode.jks -destkeystore dsa.p12 -deststoretype PKCS12 \
+ -srcalias testnode_dsa -deststorepass testnode -destkeypass testnode
+----
+[source,shell]
+----
+openssl pkcs12 -in dsa.p12 -nodes -nocerts | openssl pkcs8 -topk8 -nocrypt -outform pem \
+ -out dsa_key_pkcs8_plain.pem
+----
+[source,shell]
+----
+keytool -importkeystore -srckeystore testnode.jks -destkeystore ec.p12 -deststoretype PKCS12 \
+ -srcalias testnode_ec -deststorepass testnode -destkeypass testnode
+----
+[source,shell]
+----
+openssl pkcs12 -in ec.p12 -nodes -nocerts | openssl pkcs8 -topk8 -nocrypt -outform pem \
+ -out ec_key_pkcs8_plain.pem
+----
+
+
+
+Create `PKCS#8` encrypted key from the encrypted `PKCS#1` encoded `testnode.pem`
+[source,shell]
+-----
+openssl pkcs8 -topk8 -inform PEM -outform PEM -in testnode.pem -out key_pkcs8_encrypted.pem
+-----
+[source,shell]
+-----
+ssh-keygen -t ed25519 -f key_unsupported.pem
+-----
+
+
+Convert `prime256v1-key-noparam.pem` to `PKCS#8` format
+-----
+openssl pkcs8 -topk8 -in prime256v1-key-noparam.pem -nocrypt -out prime256v1-key-noparam-pkcs8.pem
+-----
+
+Generate the keys and self-signed certificates in `nodes/self/` :
+
+------
+openssl req -newkey rsa:2048 -keyout n1.c1.key -x509 -days 3650 -subj "/CN=n1.c1" -reqexts SAN \
+ -extensions SAN -config <(cat /etc/ssl/openssl.cnf \
+ <(printf "[SAN]\nsubjectAltName=otherName.1:2.5.4.3;UTF8:node1.cluster1")) -out n1.c1.crt
+------
+
+
+Create a `CA` keypair for testing
+[source,shell]
+-----
+openssl req -newkey rsa:2048 -nodes -keyout ca.key -x509 -subj "/CN=certAuth" -days 10000 -out ca.crt
+-----
+
+Generate Certificates signed with our CA for testing
+[source,shell]
+------
+ openssl req -new -newkey rsa:2048 -keyout n2.c2.key -reqexts SAN -extensions SAN \
+ -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=otherName.1:2.5.4.3;UTF8:node2.cluster2"))\
+ -out n2.c2.csr
+------
+
+[source,shell]
+------
+openssl x509 -req -in n2.c2.csr -extensions SAN -CA ca.crt -CAkey ca.key -CAcreateserial \
+ -extfile <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=otherName.1:2.5.4.3;UTF8:node2.cluster2"))\
+ -out n2.c2.crt -days 10000
+------
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/corrupted_key_pkcs8_plain.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/corrupted_key_pkcs8_plain.pem
new file mode 100644
index 00000000000..4b2271a6f39
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/corrupted_key_pkcs8_plain.pem
@@ -0,0 +1,24 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDesZnVBuxbT4y7
+KtIuYx8MUq0sGQgVbxXSBG66sWDU9Qoo1HUyra0xXCONgRMBT9RjSIpk7OOC9g8q
+ENNgFO179YdHVkrgJhW/tNBf+C0VAb+B79zu7SwtyH2nt9t378dmItL+sERkMiiG
++BS/O+cDz44hifDiS7Eqj/mJugAhLjWSUyD+UBObxXvUsxjryKeG3vX9mRCgAcqB
+xH3PjI1i9DVaoobwMbwpE5eW2WXexOspuXnMmGfrrR6z/VmdHqe/C3rGdJOX+Y0c
+yOR+/Vuzisn+nLeo/GJx2hIif8rKiNRyAdUXfx+4DLYJBN2NUbl9aP2LP6ZC8ubf
+6qwhhB0XAgMBAAECggEBAKuzP6qSNfaJNTayY2/EmRHFRSP1ANiV17sgE8f6L3DC
+pdypQtuaMSkXo4nc9SxTwqvyKFJ8m0ZENZj3dCJmwFyNCIqmLAD7HFW9MdRs40WJ
+HYEv0aaeUyvRo6CHD74/r/w96XTZr0GZssmtyUFRDGNRyoJter7gIW9xprLcKHFr
+YTmdaAXbOm5W/K3844EBouTYzYnZYWQjB3jT/g5dIic3AtLb5YfGlpaXXb74xTOU
+BqY1uKonGiDCh0aXXRl2Ucyre6FWslNNy4cAAXm6/5GT6iMo7wDXQftvtyK2IszP
+IFcOG6xcAaJjgZ5wvM3ch0qNhQi4vL7c4Bm5JS9meoECgYEA88ItaVrfm2osX/6/
+fA8wYxxYU5RQRyOgLuzBXoRkISynLJaLVj2gFOQxVQeUK++xK6R182RQatOJcWFT
+WwmIL3CchCwnnXgPvMc51iFKY94DbdvrRatP8c5sSk7IQlpS3aVa7f7DCqexggr5
+3PYysuiLirL+n9I1oZiUxpsS6/cCgYEA6eCcDshQzb7UQfWy//BRMp7u6DDuq+54
+38kJIFsPX0/CGyWsiFYEac8VH7jaGof99j7Zuebeb50TX57ZCBEK2LaHe474ggkY
+GGSoo3VWBn44A1P5ADaRGRwJ4/u79qAg0ldnyxFHWtW+Wbn11DoOg40rl+DOnFBJ
+W+bWJn4az+ECgYEAzWduDt5lmLfiRs4LG4ZNFudWwq8y6o9ptsEIvRXArnfLM3Z0
+Waq6T4Bu1aD6Sf/EAuul/QAmB67TnbgOnqMsoBU7vuDaTQZT9JbI9Ni+r+Lwbs2n
+tuCCEFgKxp8Wf1tPgriJJA3O2xauLNAE9x57YGk21Ry6FYD0coR5sdYRHscCgYEA
+lGQM4Fw82K5RoqAwOK/T9RheYTha1v/x9ZtqjPr53/GNKQhYVhCtsCzSLFRvHhJX
+EpyCLK/NRmgVWMBC2BloFmSJxd3K00bN4PxM+5mBQZFoHMR04qu8mH/vzpV0h2DG
+Mm9+zZti+MFRi0CwNz2248T4ed8LeKaARS1LhxTQEkECgYBFsPNkfGWyP4zsgzFs
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_encrypted.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_encrypted.pem
new file mode 100644
index 00000000000..a251de23f48
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_encrypted.pem
@@ -0,0 +1,15 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,BE9A0B63873F6B7A
+
+lGSpJkwN0J9p+2Wm58706EYz6mmjgz7okjMtsR87GMIiK/wVwjKmyUa73QTVVs15
+N/EOySftBk3VUSPx9G1ZMxKpp3l/hvkIcsDDfCPAZFqwdQQJ8BEeF9jDd5ZoI6Yz
+Yus1+X8A1OpX1O7PCZ08e2fLeVuEWg62/JQcNukuvL7AKm+qa1sda5/ktquv2eMZ
+nbTiOE3Xe+uDsgABQdy1h4EsMEaMdE6QrWdxLGWDGcdzSzfltvnhmmsK2CQsV4e1
+huQeb8ylShJuIr+mgtKgUlIlJwSd7ka8hIdmGt1LO9+NZOPUGN04daQkETtfwsmu
+YIYkh66CuLbT4nZny64Spa7AeINSmf9GA72/QtRSo3M7Khlw/95Lz24iKAy7/Lbt
+AKYenSQeJtlNgWzPcDIeUrIzXXmAXHN5YGMg/7X0h7EGu5BxYbLydkBRvSkV9gzU
+Ms6JD5aON10DQhjIUwUcBnhSnwPPpIVa2xf9mqytkcg+zDgr57ygZ9n4D+iv4jiC
+ZJuFCFrgeqHrCEKRphWRckyhPo25ix9XXv7FmUw8jxb/3uTk93CS4Wv5LK4JkK6Z
+AyF99S2kDqsE1u71qHJU2w==
+-----END DSA PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_plain.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_plain.pem
new file mode 100644
index 00000000000..a64642fc9ab
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_plain.pem
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR
++1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb
++DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdg
+UI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlX
+TAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj
+rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQB
+TDv+z0kqAoGAd0xuuUUSAXsXaQ/dp9ThBTVzdVhGk6VAcWb403uMXUyXKsnCIAST
+m6bVWKjNxO1EsP3Slyd5CwbqIRUBK5NjzdQP/hHGtEIbqtYKY1VZI7T91Lk8/Dc/
+p9Vgh27bPR8Yq8wPKU3EIJzYi0Nw8AxZf10yK+5tQ6pPUa3dH6lXt5oCFF1LyfuB
+qBYh7hyIsfkb+cZoQ57t
+-----END DSA PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_plain_with_params.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_plain_with_params.pem
new file mode 100644
index 00000000000..0a2ea861b9b
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_openssl_plain_with_params.pem
@@ -0,0 +1,18 @@
+-----BEGIN DSA PARAMETERS-----
+ThisisnotvalidabutwedontparseiteitherwaykFJyVA+0q1vAej5iQVmUvu1y
+fuA5axTA5IT86U7acP0KV8eawbDXVhqiP0zcSeP731coxJaUHC6XB0FVMhYi4fZn
+fexykg9Kxe/QBfDtcj3CEJNH/xoptJQVx3hi+0BPPK8+eUXTjwkQerGMwUD7UQak
+xuUS/22GakHZV5G/kCc=
+-----END DSA PARAMETERS-----
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR
++1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb
++DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdg
+UI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlX
+TAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj
+rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQB
+TDv+z0kqAoGAd0xuuUUSAXsXaQ/dp9ThBTVzdVhGk6VAcWb403uMXUyXKsnCIAST
+m6bVWKjNxO1EsP3Slyd5CwbqIRUBK5NjzdQP/hHGtEIbqtYKY1VZI7T91Lk8/Dc/
+p9Vgh27bPR8Yq8wPKU3EIJzYi0Nw8AxZf10yK+5tQ6pPUa3dH6lXt5oCFF1LyfuB
+qBYh7hyIsfkb+cZoQ57t
+-----END DSA PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_pkcs8_plain.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_pkcs8_plain.pem
new file mode 100644
index 00000000000..fc5f17ce898
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/dsa_key_pkcs8_plain.pem
@@ -0,0 +1,9 @@
+-----BEGIN PRIVATE KEY-----
+MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdS
+PO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVCl
+pJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith
+1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7L
+vKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3
+zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo
+g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFgIUXUvJ+4GoFiHuHIix+Rv5xmhDnu0=
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_encrypted.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_encrypted.pem
new file mode 100644
index 00000000000..69dfde4b3c5
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_encrypted.pem
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,692E4272CB077E56A0D4772B323EFB14
+
+BXvDiK0ulUFKw1fDq5TMVb9gAXCeWCGUGOg/+A65aaxd1zU+aR2dxhCGXjsiLzRn
+YFSZR2J/L7YP1qvWC7f0NQ==
+-----END EC PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_plain.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_plain.pem
new file mode 100644
index 00000000000..e1d0a6a8319
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_plain.pem
@@ -0,0 +1,4 @@
+-----BEGIN EC PRIVATE KEY-----
+MDECAQEEILEXCgqp9wZqKVmG6HTESPeCyx2O4TDoFqyILz7OGocEoAoGCCqGSM49
+AwEH
+-----END EC PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_plain_with_params.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_plain_with_params.pem
new file mode 100644
index 00000000000..2ad57473236
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_openssl_plain_with_params.pem
@@ -0,0 +1,7 @@
+-----BEGIN EC PARAMETERS-----
+Notvalidbutnotparsed
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MDECAQEEILEXCgqp9wZqKVmG6HTESPeCyx2O4TDoFqyILz7OGocEoAoGCCqGSM49
+AwEH
+-----END EC PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_params.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_params.pem
new file mode 100644
index 00000000000..3424393d3fa
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_params.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHQCAQEEIGKZz2dsNCzJQElLteZe62XZzAyG+p3Dng/Fo9IPKThmoAcGBSuBBAAK
+oUQDQgAEJQHRtUfNOMA81RefXOaFJLTxbtjPU0rOi45IHY1ug3rzflxwz7NtqHH3
+aP02sbsAmpHFiL9db7XmNDK2+58vWA==
+-----END EC PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_pkcs8_plain.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_pkcs8_plain.pem
new file mode 100644
index 00000000000..7e6de544247
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/ec_key_pkcs8_plain.pem
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCxFwoKqfcGailZhuh0
+xEj3gssdjuEw6BasiC8+zhqHBA==
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/empty.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/empty.pem
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/key_pkcs8_encrypted.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/key_pkcs8_encrypted.pem
new file mode 100644
index 00000000000..28059d5a226
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/key_pkcs8_encrypted.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQMwDgQI2jwlFL0XId0CAggABIIEyMujZbpG6zKb2pVu
+soamTaoLcZwNofS9ncGIEH1nbI8UpPY81VeOIBm4mneDt8RU5bIOXP4IZEZY9uU+
+pugKQ3hT8vBQjJujjuctUPaFxB0kGEeITOInY2jn2BFDbUgy5Z7EVD4G2K06SDDK
+oD+twbzZo9x34VizwpHHb8wE+DFyYc+sp+Re2Qk3FReKgjdJezfcRHbKrrlx2rJ+
+k/YAPmzcFYVbuUiB6HY6BGzSJO1JxT8iNJE+Hmk3ZLXG590hp0vuGSkY/ihbeix4
+1rQs7u4riqXJ+DJBmXt/wXUij0/k6s4igACNsT2MkZkGEDkzqzE+kj2VYOHSX+Wd
+5W0WCfftcsIQ8eow4ACec/Ns9ionLjx1xnbTjRMkpGgbVsreupU9AQ4MhLNNgwyl
+six/cxUxTvH8Modd0/4KQFkeo352A6+DKCaPZ87SoF2Rge1otcJaZVcX1gBvIztB
+/xzYwyUydQEwblU0kCYWRgxlKP9jxFoke2RX1BodRfAMNDxS0XyYrA/JzB7ZRsS7
+QGYPy/PPb014U3KhpJdjwbNu2VaCVdGryYA9+BTP+Vzwcp8MZoMPnnjnBh1YyVAj
+c7oyzKU5e5SVsYni1Kt/536YxQgFCAUHv/g+zQqqGEvyiMXhsCwVpoy7UcFYgmlw
+40g3+ejwvlO3YA67gQQKebEv6/Laz1hVNiXT0m3okAXWxXgF/g2eBO5NTRdtaWn3
+VNH5ub+LOr6cMhk9BAtKgRG+xeh8/2SqH12UbwtlmxqnBAfHtqlE6yJ1ViMDHxF9
+101xJlEONmC3fcEAjShK6LEbFwPJns3WbGc0ds36CzXWtO29XGssr+YoiF9e3Eus
+/XQjmjOJxRoWkNEYsxlJ3IRH2vUcdCoAp8IlD7JYxx8UBCSJDBo7/0QKU6INeWjo
+5+aNbaLAJULSKo1LTZjjANm+G+KcSnbn5Ed8fmY+D61A5/7WMIVxq/uDLFvxCnRG
+QcLbtqbPztiWwWZOuTwNTA3bfAhEG0ZzNr+0z33jW5T9ChvdutgxJMf3Khazx9cx
+mWyCpJwtSv7hSbp4nCS2fmHCum2yIrOnou8TSOlQFERZ3UEZMgLpWeupH/W5C3Ad
+rOspFrK6K8a/iNSs5OdYUIK2iHddTs5u7AEZ9I5MTuYnccuGuXfQTTA06TJvJTax
+c2oDbXMnXs4pHLiiSRp34IHIYubdrj8X5vTODC5djl8h1167ToXo5zGdXqT1om+u
+4ndNLbbI1vld5G7KAL6TlTETg+N7S8v3KYoBEWzykwgqqppWnWTqPWQxM8Iph5ly
+AQlzz7feERi/h/s57RZ5ksoVAdbtk2U6wgHnLrWhKZ7+ZOAfpNAjGHwWyXTzylXo
+zQ9A8Kmd0jBMsru4fsGpldf4lTsqO/abUSWrAAREGnlz/ZjEb944Yox7JUhWC15C
+WxXK2rFbiF3S0HtEvU17rdn4HCsZBilnY+hTpHj1MA6O451/A3ghxGXFKz/9LUcS
+YBRQJaSM3hTqC3WoTVBeVc5nCFOpu4F89JqhEgXOLKweueMbTMRSNm93tXWT13s3
+Q/o0pNJv/K6+bIQwsX/oDafMXcW7STxQJObbAleRbcn8/rGS2eEnVZ6907faUR/L
+7eu9vgAa/jh9FHpZ0Q==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/key_unsupported.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/key_unsupported.pem
new file mode 100644
index 00000000000..96f95848d09
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/key_unsupported.pem
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACBqIPMG94HL7zedFzsvi45mHS8ZuyLQXqvHpHobcdNCJAAAAJimRM7VpkTO
+1QAAAAtzc2gtZWQyNTUxOQAAACBqIPMG94HL7zedFzsvi45mHS8ZuyLQXqvHpHobcdNCJA
+AAAEBvVc8FVPGUs3LZ1o+LnjW4uUlEnk/5LQQ9yO2eiI3SFGog8wb3gcvvN50XOy+LjmYd
+Lxm7ItBeq8ekehtx00IkAAAAEWlvYW5uaXNAc2VjdXJlYm94AQIDBA==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c1.crt
new file mode 100644
index 00000000000..532b19692cf
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c1.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAOycKYSPiBuHXuHsqaE5KyTLYTqlMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxM1oXDTQ1MDkw
+NDEzMjIxM1owEDEOMAwGA1UEAxMFbjEuYzEwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAM/q6yVK17PHtdsO5pM6DNU6pnOY/FQO+c1JpD2cpOk6B8yokEtFR+a0
+QsdsqQewAGBG77u9jQVerJr6fkPW+AeJT7eEBl5rqYDx82XgeJS6dAJRvclrxsOL
+BDDWsImDIMes0AZaE54P6LDGBooH3XhidTyFj2Gp9fozVY8PWFl5AgMBAAGjfzB9
+MB0GA1UdDgQWBBRLyFFKNa/ll8mohWv8TJyzCzyOmjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVz
+dGVyMS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AFmuRJmgPi2dwMwhfzGdDB6d+FLxQOcWSqj10e7Iq+bEydUjYZubp1K0/9dbUB5o
+9iUvvFbZirwhRhcYjB5s/sEJavXEOXQshU8zek+jBuO+uKdndmiA5oGbDcKAEcbH
+aPbq4eJcLAT7RJWlW66nCZNvJNnSh+DmV2w9XUZBG2ryOlq5OYCmLJ57TBKgvK3C
+6gOECdImj2mvZ86xBmjZXZ6JVK0ZbnClIFt+3b+R6l/IUkMf6t0VVN/cs4AB7bTX
+c1E4L4WHUmO7enzMZi1LyOWs7BfdJjjx/YnsVyh6PqcJTt7896ohbnfORmtuMZNb
+eO5el0aBOXZaJb/MiUC6E5I=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c2.crt
new file mode 100644
index 00000000000..680547f5bee
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c2.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUV4XHn9tdtxmUFg8gitI7WNN145EwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuMS5jMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAlC1TOrM0KvZxZ40BCef2HCQOGsFI/IUmFCVno62Rq/DZnQbpqs9eyBjD
+dJ9lMET4arkqJ1Vvg0rodZWCg8TOU3+Wr1xV1u2v4oBTdwyfoMrZxKW3NtMGQRdr
+suTkfQm32ouq4eJ8Xcf6ziCwApuoIKDPRZipu+9Jqmywqw45a1kCAwEAAaN/MH0w
+HQYDVR0OBBYEFG4GgmhNwmrhBpwtZAMtv3bsH2PrMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUxLmNsdXN0
+ZXIyLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+ZNWqkJ8Fl5DwSRgQfUAjOjEY7+PCAvX2qKY8I9Z3DiB5D8xFeIP0qrz78oN8K8JY
+iJXFPaKFpYihejHywSK7/A+myvZlOUDbPx5rULtsYVeK0e7n2x8htTVD5E6M0nRP
+Jdb9WittiGe4muO3e17wdwSLEOrRfp+YmBnRy+7Q9BOix4v5y6HWpYwGdX5Wnj8N
+devs0ceL9Ymtdd6lSEmDQRxBGQ3xXfBU4+Wl0Ec786OjxfsE30hBRFH9S/eQwfE/
+vGxB9Bo49I1Jar9DRMxnWjdPuoJptvrFHeByejovBeGfjOmXDpl/+eNk6JcnXjH2
+9UTKG8M6OF9J2SVOWCzU4g==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c3.crt
new file mode 100644
index 00000000000..a29a86e3f67
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c3.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUGqZyGvYnT/TnwhpRix5jqfGzMHEwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuMS5jMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAhXKEuM1xYezN98jNJftpBGSAQ4jM0W4nrP86NhflKhCCNnp6PSh651t4
+4+v8tPo2ZwhaBAkchrfDtHKBuT//6PIteyEbtsj/ej2OztQ9XO6h4+3bL6ccVgfM
+vm6YD1y6TjTM9fCvpbtqrBMouEOYkPPLA6lx23JyW5mJ3Lwwno0CAwEAAaN/MH0w
+HQYDVR0OBBYEFKEfz2T5jwYqWOgbnZOJL2mLkqtAMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUxLmNsdXN0
+ZXIzLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+Bd8aXS7DvR5mNVz7aSR1qoTBHKVLqIrUju5gKFsIrkfm0mEgvhx8T9m60k5h+sgD
+TMaoHatMIVssOaNoxYwvKtnnuHKMvrkJLb/qyaiDfn0zO2g0jvWMtmaZnShrE+jj
+la1hFKCkxblUgo1d0IQaONaDpgS2PXPu1Iah7h4MPB4BZdFNT5afnKro3zAfiKA7
+lMhGmTwPKTDwkOETNJQ4ETFjZzY2UxFjLsRzbrXDeto+UrU/qJa8jzCWI8cI9jFc
+vffGGldbRWoUq0ALZSbz6W2psf/xAo6tSkaf0MDSMYRZ9mFVmWBSREITn+12gp7g
+5A8wNJujWbyAR0j5GXXZAg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c4.crt
new file mode 100644
index 00000000000..e1838cc5b4f
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c4.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVANq892kwQ089Hnpd0M4dSCmHpvARMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjEuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAJVhOQxK4DAxYsFDcm42dl0DdpRCqxYFecP9QmC2cniv+sMUSRLsti8B
+eOKawlWL+NQK7CJhAQPuYnLEBiyhUIFz9dAVozHyOqBKFbf2L3A2nIPuom22UiJN
+79k2YXZgagSCdCdRX8WTvTRbbN8WYRfE/wLO4SBxwW2f501ET6pTAgMBAAGjfzB9
+MB0GA1UdDgQWBBQIGCed24kXamJPxK4inO7BWteawjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVz
+dGVyNC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AE2ckMOf2Nrh+TfHQwvZWIWhENeIih4A4ivgimfcGWumpCho4tusNu/RIh2DxVqy
+4kJSqQ6NggGADDDPmh2p2UTa5NR2RF2FQGmfNtkFwp48tE/YXWurts0IneidoGYC
+RXM+mVXTNGlPE0BrgwS8tSKRRXh+lsvS9HH1wkLUSa8tk4PWqln1RpttiHYnImqU
+t4d38vpk0AfRMalEV5atb8eoNkKVOfrDiJ8/iA/zJ7qh3PUaU24taJtP1MNR2mo3
+aXZH1GCA+WUqWAUDN8TXHv9TABh8IggmpK39weV17BAKFHsVslq2auyDaFcmoJk1
+tLXpMUUJweWmFTRqQguKu8k=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c5.crt
new file mode 100644
index 00000000000..a844d630a2c
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c5.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAJ+D63xrhVvDF8SCF0IN6olyWI9hMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjEuYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBALGUvDdOnTe62apHl5sXV6Ys8GYqKDJ0e1cCQCKgxu3MyCueXC1xdhYJ
+ceA3PTmnTRg7KqYhJLZi1sujBOfuy7vsg5r/7L6EhWDCM/d2QfF9ZUft5ljsEGYN
+OmGakQnU+mFOuDe18hlp72tavC2tdPYHaTmd0t2f4J9ovxQznO+jAgMBAAGjfzB9
+MB0GA1UdDgQWBBTgPsBAr0vFIhwmOhBkC1XvlAGtvjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVz
+dGVyNS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AB6nwwv8Pvzmj+/qxqyUu+doqR/DNu7J2ZoVJ4Y/kbp8Sya6GBVocN/Yaj+5aTv3
+phegvSvXTuw38gUuadGHSJ0R+GgaZNQ99HgMGCaePsFSf1Qya3vnK0308n7MSr8F
+4pDnJCmOeOZQkY0PrMHx5KW+BdNWU3bvGALQubVo+nJEuZYTBPt52AkweMbtubiS
+kS3v/SKi/mD0aKWS8amgAlCAFct419gE7frWAsEDXmQU0KDaSE37yx+0CbvqzlCe
+EZRRpgg6R1px1F0WPU1SkCfQyhTE8MMz8Wj1dL4PkCJn7ku5CRF65VgA48t6Ecpt
+4UfKfyiO1rcbZKA+UKovHjI=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c6.crt
new file mode 100644
index 00000000000..9e3093aae54
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c6.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAJHJ9P/gVQNv5i8q8tW/UzufE1cdMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjEuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAJGKOOMmMfmt+9VRZfYsorzOWLxWRtqD9VjRimbBVWBoIFYf+EVyEC0E
+/sg8G9eWAcSEUJ2oDp5dnMuXzEZrA3aaYeDZjtOYuHF+i+PFQQFlpY9A+NapdhJe
+9CU6cvL4ImRyatPxw4A6QLLetWHbDDIYA+6iYtmkKTkMlY6bboSzAgMBAAGjfzB9
+MB0GA1UdDgQWBBRs7k4fmkFw8RmVU1f+p9SY5qNwnDAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVz
+dGVyNi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AKvKMX7eiwShOetFoe8CQ0jls5aJ2119gp917eq75XZE8HGJhiWlBA5qcCCxCrtR
+Cy1BbuHiMqPni/7KaWosw41dxyysJOrsPGw7QYnhda+ji3mtFVxT0Zert2DPKkxR
+Fgt2VWbkF/keMKDGc2vrpyq7YVc0RwDjTzEURSLxI4p+t/HbWQXLAIGRjVXneoUt
+bc+I/2/C5chV2qTQd1xC6OfnixJ1234enIL+0enypLx/8Ca6i8+Gl13FpyFpO/ik
+yY3Xe7S4rRAsvWpHRDWIxqA/M+fzhOb76nLC4H4TGkuAJ6EavsnaHHHOngbL8Ag0
+zFhXT0Vj0GucUzjx2pjFhfY=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c7.crt
new file mode 100644
index 00000000000..5301576723e
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c7.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAKo0NbCgIbl24/edkcXtukrKEYx6MA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjEuYzcwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBANHSoRZvMsCdrQREwlLHR8xFRPrlW/qC1VcbMDkwSdvFOrPh/ykpPn+I
+kKrTQ/kOBCOruPSh7x9/5KB4EbkMJnIo+XQlLgLbAUeMGSS11IKpQTS7S6noyxde
+7xU0Z4u/MYk0PS+QgYqDU2ExoY8UN7VGxQg9zSzy3dublTUfVXPbAgMBAAGjfzB9
+MB0GA1UdDgQWBBTxpLGy+DAZqPn1o0uRboFaeT0D8jAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVz
+dGVyNy5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AGPN3G8zC9wT+FPDUJzR5aiXWkBN6Bn8pYaDZyWuWFQr4l0m57sX91vOSBBvXtYv
+0gcz/Nggkz2TpMokfXBOoioeHywYIycy+9F9obbgKy/f5ejCGv8F26FS4UH4WVqs
+dIHaWy77od7SUuBqjlOYBAK13GNZt/4rkWSNsry3p+YoVxmEoUW0Y9BtXDXY2M/U
+ewTEbC1oZHXeyNzgI6Njw5d/hELKMNFwq2RON6tU/XHXABXCdzFkIjHvrM+N8a4N
+ju2xbQALjSgPWjYprjCiYHW5z+aB+lAKbCCUcsrMQnE85Bx1DpUs1oAWYo77h7Xd
+uAX6yQ0JODD/TpNGoWktcUQ=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c8.crt
new file mode 100644
index 00000000000..327d80885fa
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n1.c8.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUYMQ3IxuiB6pn0PD2FbQpl52431IwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0
+MTMyMjE1WjAQMQ4wDAYDVQQDEwVuMS5jODCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEA0ExMUocWZ0c7F0gpF9RXw1Uogl79PxBKIc2Jd7YcDVNDWqnyMWNcueeh
+5bBoM1SrPt0q2PDld/rpBeOoBqZqRMfNu1t2J+ij7bvq/eh/7111hiOObqfeWe8r
+vOKcuMuP2XySO4SnStOCpRTbpWJwlWzvp2UewDQ7FKF1tt0BYnsCAwEAAaN/MH0w
+HQYDVR0OBBYEFMZDNcpbk5GD5ynwpCQOY6VDM4gSMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUxLmNsdXN0
+ZXI4LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+PbfEs/JWjdw5FUuj6+vb6hdpnkv+qCxX9ayZygmgzAd0mgYRpm51DQFyIbeBUYdA
+vqHDiKMT56ODM4n4ij6gWwyzmSxLRbtCTcOC2oVyhyGlwmkYXw/9/JOUMj3oz7SN
+8iRtsICqJwcbTGenvHN8Nfr1qMvl74K0foNE/hczXMcYNQq+LbYgen5dejFbOSmH
+V2oE0e86w7pthriazNSmivWQEeDAJwTR51oOkfm2KMVA1adbqBB7BP8eA0uOO43L
+SNAArh9Bzlm9/5raX/YTL6In7G3/wSFvIuJUYwV3JW57itzaBufZ4G5CCVBulGN1
+ltKJJgSsxo6InUTglO9VDA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c1.crt
new file mode 100644
index 00000000000..5153e2a762d
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c1.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUNzsUuUWlDaQigjdV2GBNk6NJfAIwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0
+MTMyMjEzWjAQMQ4wDAYDVQQDEwVuMi5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAm8aLIeL8o3DodD9VWa0KvotRwSUtWX+qzAFgM5SqHHymlDnwRJq6gutq
+nCDCos6TGihA6bnlVw4eRnjq8usw7cyJW2iIIFPr4d36DN2Ui/NGdICP4RMClrgf
+5sC+GE1jln0W7Jj3f76jB6HE3BbU6PCHdlAtgVcQ4j59y9dchI8CAwEAAaN/MH0w
+HQYDVR0OBBYEFOMdmsBGJx8YHfiziaJxU93Fc6C5MB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUyLmNsdXN0
+ZXIxLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+g/ZYdzwpQQQ70gIZ1jUSRkUUXAU8LNTLRx7fGuz7t0RNZ5MoUIlX/9GiJd3BPZOK
+C3fxU6clHn2PA2p6ZyPfR+C7jW8akyHzqAsrawzXg0fqtlOwm1U0njNwt7xLS3Tn
+/naLQoWYuj94rVzoV3wYjehcl2zJovudA2IrDeOGU/vAj2zwTnhagQ5eDQVf6A8H
+kSItIg5kM+7XRYxp1VFgS61B1MGT8JWMATqQ6UyRXlI30HXWOxfL1rmWKmyNB73y
+uMEZLibNAJkAl1vOuiM6W/OHKLPQ0htJnny70vX8nGNocWsAaQyDd7NfXpghS16P
+fgttR3nz3R5lcceu3hKehw==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c2.crt
new file mode 100644
index 00000000000..fc88a125990
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c2.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUBC0p+NZGKecWH4gpX0rdVorODmIwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuMi5jMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAwD1plbaw0HGBzX3FhRKZIbz+RncMdhwHTZFLrfLbRm83AEhvMyhrBDAP
+1nyB+p/3Mnsk+eaTK+Fo/KBjdakbMLfS/Ewb9cbr+k9ZbTLGXIvULrRqefWvgFN1
+Fu+azjNrDqHS/qh4833+hnqyCM0TEEGxkRX1TIvrdbQsRw8j71MCAwEAAaN/MH0w
+HQYDVR0OBBYEFLwdJ8K91/Xq8cEGOZvM9/4G1gvPMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUyLmNsdXN0
+ZXIyLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+FdgI/IHCkZKV72pjgI+0Pz9nOvplX9SdBHYOQHl6gKdaa7RsBlqbY6VIFXG4ZNh5
+H/DWTixiEhgquNQJbum7LNan8ugMdsQXXo+WBWOgz3mYYHcPWvU7w4pyPUraXkC1
+QbsoCqY8senXl1C2RBq4psw0jpobVZWqQJxR4RRSV4mb8E6wMa46xwXTDqoTgYLN
+qCh7ywhYYFkWIhfC/aS5D/kigcdU6IpV2hrNvFrFsNwCiNoyHmRy/AUDhGOE0BRp
+8WjHLE2gTsR1hIF1jNIN7vebkdqq2igxs3wkEp9tN7af3mjwwIasi3ZCjKoQHVUC
+EIwmFsFPsgQINx86HRWoeQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c3.crt
new file mode 100644
index 00000000000..14b9e54e29e
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c3.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUJOYUNCOnak39xRysYs4KSzQALNMwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuMi5jMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAqWUXhz1gV5BnMS4T9gqVyod8OJL62oQ0nR0WPdyv0yODkm7cmMcvuWVk
+2sPtyGHv1gyKcFteLsBH/1TPV1zJGk/ecrCJlmyfyhnJYKuahf0SN4U9EGmtar6o
+5ja5RVWiEmAbNnpJQPGVrBPLI5zmhT/C5hvieY2sGwZP22e0c7kCAwEAAaN/MH0w
+HQYDVR0OBBYEFIx2Qg1dSxouV+t8f1G7G4qw4OfxMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUyLmNsdXN0
+ZXIzLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+diaaL/4cK+ycmIuyb9pf70PZ12/mNSOovYX0G/ZmhcuISxIOwig2LWz2DPlTs2wc
+QBHsmiIVy0cvMM+cHgOgKz/gr1ZgkS8CoRblLh6gKHVrSkixk6oz8FABVrqmkSMw
+McjMft3+7thITso2jRZJWRl2sbWN+cs0Rwjw7HajjHSLbmLu0/6rwioGTY8TpQJT
+K3t0OkvBFCUQEsN1pkkXgncAoxeMQQg0fl8IJ0mrGyEjKgtqUuDkDLVdOY+y8oL/
+vbzpNHb93LbFl30Dl0Z4ugcUDPbp5tDzmeHMFbPGcKZd9s/TEInZbb/AfpGMq93t
+t4MVFO6u5XaqOV792rc+kQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c4.crt
new file mode 100644
index 00000000000..b94e8b5922a
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c4.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVALfaOUWIcNx5DoNpszbsieO27BDlMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjIuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAKMaYHZ4RiQN/cACOxN9GEyNtxwXC1PD5rD1nPCH0Efyg5SLcDzbBj5Y
+VS+BGl5HIQ3hwX62vnI9pRM8GJOZXX4UGHQ4gdd3B+qbW3n9K29cSqnxulIZiE+A
+x6LOXwwEzSag1nTEpJQo09LZPusyzXnicEJ/RpC0krAa9g6gnvNRAgMBAAGjfzB9
+MB0GA1UdDgQWBBRsXxUJ6YradZoLR5+cQBXgj69aOzAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVz
+dGVyNC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AHe8DhnLXUPvfbKWV2h2NVI1x6MuMBFcDQ7HgukHwMMydnHclVZGffXu8ZcFfy4T
+NxQ4N26irZlwjfpXSpZeE6b1fZ8x8B+3czXSZRGJIi8muBA2/YJjH1ul46z6wdgr
+aR3RYQTYzEicM+qY2SfISEUqx0RGHxVhoFBwNaS/EZWXyi1XZfjD4XQri6KXJIgX
+yf+zr5V0ZVbNSEci3gUR+TfjG5RWE/r8XiagZ+h4TJidAjgt0CPc2vONbgcgcb7k
+mhRA92z/eT1etHaK29Ne13p7Y3NI2MxWHvyygGICBcP5DsthRVCNAbFFq7N8ym8Y
+2ensWXgNScolc5SjzQLUwss=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c5.crt
new file mode 100644
index 00000000000..c7fcbf3c7d7
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c5.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAK7v7QnhK4+lR3ne9GSfZiGiriXiMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjIuYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBANLAWJxq07CPGG6VYspUbzyEMn6pBE0z9Or69wrDOKM7CVM8CzrN7aw8
+zYDLuOZy4cEJxLJKvtw5wQfh/JELcMH2WNLIFNABl5+m+FpNLBGgFMC48NUCfPex
+D7JUPAc7oiaZQ/CFCP+5YK+a5F7M9/SwVfQKKnsMPK3v6zyZkFO7AgMBAAGjfzB9
+MB0GA1UdDgQWBBTKJgGOBVnP8ZNUNlZXD0iNkRRDEDAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVz
+dGVyNS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AI60ZuBWX9IFBBfGSx66cDVV6lCiwtl2h39SHDQoCPdXz0uLdpJqLEhmpQwkf25T
+j4g3bmfRMTZbsztEZFNDUkyX7hlgmTEFmxyx12Z9NtOTzp9xaZdhAr7fAwBRcWjJ
+CHPjrfjR/5CVXtb5XcGdGg18x097khfFOdubyoty4sJ/4wT4zoaZzTLGskzzvvsn
+BSMJdCS2kM7ITGxsUYC2r+LzKR2/nX00o0xefGzgJkPr4fdDwCxsobYWspgt2SkZ
+pjHV1/Qf9qdpi4wxcvZtVh3+YT5WGJRwTsbBicZ8i/gj88qRi5cqe1XiJ/05MGrt
+XEM5DWun3J9yjav9v0jfZyc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c6.crt
new file mode 100644
index 00000000000..649acff7ce6
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c6.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAIrh/Q7uY55aIFW6/o/ToRCGAKLAMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjIuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAICwXz/hU7DraQWX8TJWd8hva4KzTKOpq8JjnbCd1n3ovAqbDP6GkgVA
+JxY0eMFwP+u4jN2JZuTISWIUOmLGosyHpXsXQwbsvDLUC0JPb6v0/omkLFsrIXgB
+t2xIy7Bt3eifKUmUGO3ePi+LbgKYq7YNy1uVaFiYLR3PRul+TCXpAgMBAAGjfzB9
+MB0GA1UdDgQWBBR8+r3Wp4Dc7QfmCXkTGgz3gyfP0zAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVz
+dGVyNi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AK3Q82RwW4pqllyno6FO3OGOM3Dr2I6RN9N8A4eJShZXpyIvrgSH0/WSYolkGz2/
+NobQQBHFUYcjWtwUdoCTNrYXrENbG6j+EmW0ey5VBZNHyLc3clufGMc76uJUvARV
+OLeyeSuSjJYxUafwacIzjsJtJbmixmgweKDI8jmBIuvSohnn7icwjGx46nbagBpJ
+2et0zT16kVl6Ti/GjEYw3Q2q4iZfWaQ7WvqVYvk0gidbDwoJGP197MexeU23M8tS
+CcmTLGoj9LbW6mc5maU1pxD7h/cFoMjgHQCDsV7tyoex5ZdxrUVaBKqGT4CVrPXK
+OKyAMVQkOvxq5/QsYT+MHiU=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c7.crt
new file mode 100644
index 00000000000..88c2c0403ed
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c7.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUe1qpohqiGcra4yw7HWh348nvcGkwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuMi5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAhbZCMJKpb1FJW1h/xfK694X12jOwAp0Oo3qv2f06lSuR2jMH+2C44+/L
+7JJoc3/Xf0is/VBgKpqJpQF69RDNTU3v/JicVel0aI1SuRZfLrBNK5mGYGbevbLZ
+fAmuzMbPn+5WlBzWePNmyw431SDabPEq9m+ziFRedfYY7K6PHQ8CAwEAAaN/MH0w
+HQYDVR0OBBYEFItxCmYpuU0EV0BsB9Gbc4CDQJKSMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUyLmNsdXN0
+ZXI3LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+JorZihqwU6V6qWUU/GaXGHBMCIUtQVO6NsLbV+6YQ0ljSDlp4N6f8M2UFZZ47wWT
+t6nWpFjrm00nng8usq5OF5KM2vyHyQ4gGs2Dl2+R0+BGy8mvj6yLfkxMMytOPBHK
+NYucWh0Adjk1HqSf6Hrb1IskZqLk1/sJOoHoFnUixJ2Hz1L3Fcwl/eG4eeJ85KNS
+vTx+Yqnx3S/51euuRcIJfM+1+9nBkAE8aaS2MLpTuU0kWvtk0PBPuro4t/8iAZ/G
+di7yoPhtcwwM3u897hlRBkx7mBe5nae5HSAt3tqIGkvFQz+BxXfM8cvYOHaFyPRh
+2GrBdAXu9kFDKfrAWxIUzQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c8.crt
new file mode 100644
index 00000000000..250c5f5beec
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n2.c8.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAJC+xJO13Zt3e/q5XOGbqT8JJmGsMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkw
+NDEzMjIxNVowEDEOMAwGA1UEAxMFbjIuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAK9dg+Pl7I8v6JIQCdZA1W/1ieuKHHdhnVkNYkI9y1Kw7cPyhZVsApOz
+mjX5YccUCgu/zsNgo6K/Q/Mo9/2qxx/JCmBvaTL7PAUzFS4VPJFwiyM4rhebP38w
+TUb4YXKk3Y3GZ9Xy1vFFbDMmx4HREFi+2PacMZyrs7pCIGtvpTlNAgMBAAGjfzB9
+MB0GA1UdDgQWBBTCTGp5uFyY09VJmeqTkdEVrElUdTAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVz
+dGVyOC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AKG8Jr8rNglt/TS2LX3/J0Fsgob00H7fmV4DAuOM/Ui3VeZi1xdHm8su9s0R3dDb
+JkU8t/cI+jrg2OI54nDuxaNRX0dLPWIfb5Q2Z3cXiDdvvy/9RIK1SvN1o4XERIfd
+Vu0ZP5akVexuPgZWfEpwgeOrjlkhO5VrHap9+igvSsNU2mJtzK5iFy21nYobC2OT
+/a+qxa658RdvojerNAiYmpC0mvKv3Au94loJ8emoZOnVIS6lQivCz97tKO0L6tnI
+jOsCu7cW7IAxKvYOqtOSZxZzBHSa4QFu6HixpTITbeyJ6a8MaiejHG5fRZ3BpSIG
+BmlsawZmp/Rrd6nLq2Aztqc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c1.crt
new file mode 100644
index 00000000000..d1fa1d53601
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c1.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAKd2+KsSsV/wqMN6BTbenGb0t7J5MA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxM1oXDTQ1MDkw
+NDEzMjIxM1owEDEOMAwGA1UEAxMFbjMuYzEwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAIzKcPP+NTeJoVHNK38SvvMpHADXXN4iavSOL8iker0xzCV9EPpBCi6b
+zfiCjUqtS5n0ySTCce75Y4yuhLstAZ3DhUyKvdV3oVZMv2T2Tqy2ybrT20YwhRjs
+MXWKlFjIdWLp4kAVfMt4Mf+qp9Ou+RCUKCtYl1+caHt8K6lE4uPjAgMBAAGjfzB9
+MB0GA1UdDgQWBBRJ7Oy8e2RR2rHLjBcETcdR4DmY1jAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMy5jbHVz
+dGVyMS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+ACJxPS9L9+bStPqXjVGavLMH1OTT5Jz521oB3KgOnYb0pEewnnUpYi6Tty8cuoh0
+a8MoAF0O/pqqXYJQ9gaUBBdokg0raDcE1c0jObd7OR7IFZoG4ojVh0M8fK28ykFM
+F+Jy2nGLiW5C2Je9pPELYHmwfuw16iU65WlSYkgPAwwc2oNNnq5mmvLgGOE1kcri
+lFjQuKgQEzt/U4oRX74zHHsajC+ZYAYf5mTrz7qJO4IH8/+//HahimRUphE0o/KZ
+NY6iyRppdhWWLQFQ8+VpTY1crmwP5qyUcrlSY1zl5zkldU9dfNmz2NdjrnWtMbl2
+VdTOSAtHe6OtvsPCAlrGFyU=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c2.crt
new file mode 100644
index 00000000000..a6b388dfe60
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c2.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAJfn9TW5KLMUqkzAi+zsAHqbcTZWMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjMuYzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBALEnh4sMjt8W7vwIeW/PirZad6tqKbiCeGyhSWNL07VGDKUsAfF6RY6v
+oyGjBow/fPxQ7OXjlw5BFEgO3DxlTbxLcNk06JV7d4RrfHhCGF3R3x1L/icTg+rB
++QdAaMdHAiU6Fme5qGUZg7k2C0JO9mTnJO4tIsL+frPGRFmlNZyzAgMBAAGjfzB9
+MB0GA1UdDgQWBBT9XQWzCcEEuYHJXQVr447M/HqFtTAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMy5jbHVz
+dGVyMi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+ABd6sS7YCm+KYQKxvhM0I9k4BS3rkd3L9fRajM6gciPQhXpfO4X9lKxXtGfG1LcC
+13U8k7nV8o9VXCcNSUXtLt3jk1+qprqPfAPDWiYkaYgRImotgU5q5IxM2uCQXZP7
+BTlzBODi/e79jgzuxhbOCzO/6D7Eji4vQP3MCnikzjXJ3MMDIV+u4M+e8UuS76vt
+5HwsWQrAMl1hfxuA4a/9OhbfHRrVaYOr3czULqr+66IHetsDsUZs7JSL7qPXFldi
+oMrUQnqECwZKhqxokiY0i/mrC8frajxQbk9Y9GVSBsGess9YXwNXW2VdbyyZFwkw
+rIdSfF/kY4BNf3/c1FqVjNc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c3.crt
new file mode 100644
index 00000000000..60abe22ce3a
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c3.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUHMEbpWTGffkry4rCbr+g0f66LGwwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuMy5jMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAlMorfk1gUwZci3ta792qR6j50VUKQ5AqZrvOXk74eYzfPZiE8TJwnphG
+dfMm8Ru4v04+4pf5tTzrl0L+dKebSLvVWYE+VPz/So9jyb2gHT7/I1ypEjum7iUp
+SiVzM09exmSyMrcyRpWSRQcrMomC4EK5OwDctUv1EUqAlgbmuqECAwEAAaN/MH0w
+HQYDVR0OBBYEFOkY81GYZIxcO6x/wKKrfPah0ThRMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUzLmNsdXN0
+ZXIzLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+nKuZp21gDBXwZV+u3/QXpsR2jLp1T8oWh1d1GuJhXkHqT59DTLgaDxNt+8gxA7mA
+Kooisz68hOjBP3KGGvz+WUWM5KhwPJplFyQi605RJOdczYf5+6lRqbeCQnC0kaR7
+iSvfqyLQXc41aTL8MxVBkJJhr3N2Qui6H4H+8nHv+R9ShE2HYC9UDUcifoabc1ME
+B6wKWM9TbGSqozeH65v5yDGcC/17LMe6oKuI/kti8L3Tbcp7E2bRyt0CeYXRwq7e
+/vA83WufkhfXcZZzOvvgJBxKH1MCj7D9tIOMv9Wv1vu2ECBaYPIcClTqcSjGrguw
+XHBKbhh0L6a0jcsolV7v0w==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c4.crt
new file mode 100644
index 00000000000..db1714af713
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c4.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAOcJa1E/SlLyIMeH6LDKqwCVLxS7MA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjMuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAIwFiuTI0adVuF91ltRwyCzA2Eb9fV8JUKmlVXfjElP+XGG2CUerk8H1
+Ps0nPDFBCZB+0VM5BzjrtsEYmuEk7LJDXzoEj6L2MiYKIVia+qxzLvSfbcdJsGNX
+DrKn47sKDrUJbBDVodI43xGCplWyyhf0MS6hMe+7ttwb+LIZzTFLAgMBAAGjfzB9
+MB0GA1UdDgQWBBQJKDvefckZz3in61z5pdM6CpIwYTAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMy5jbHVz
+dGVyNC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AG6ie4xkvfaHLWhq5BtFYVQO2+z6siRz63hBySKwyCgoNvyk1h4xHbmyB8gWG7G7
+TUjCMkRovx0DIhCwtK3Ahj4APh/QyqY3d7KV4i9jQSLXfyaY7ZdvLt18RE9i3MjL
+QR4kGSPaTKlhAOyZ/qr3NdyQH56cvUEto3hgBOb71JcqpT4DBc7w+W/wNeSSPDb9
+/7m5Oq5ntS9DzJBpGcfZ4IHtrgZu9x34uYLkYCblYiUQ4QQyyQae6YyihfzH9QsD
+vt5ja0lueTLuA+LAUv7OxDQm5USXQeRmXYT+Oq+MBKoJkMznftKYnWK3tchwr5qn
+2bQoMq2HNQtemjZAZ3IoQYU=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c5.crt
new file mode 100644
index 00000000000..7ee49509b0c
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c5.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUVSG6oHWDOX3AILqaPWoYx+i69V0wDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuMy5jNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAm+gpSNeO4opovT+vEOBd34pKfiCaIqoe0D+vR60gB35glziDShITOGMs
+04qUkM44nnv+d/Qib2BdkNlze+l/Sv92r+0DQp+MRzdNE9GkuV4B8yF99hpi71hJ
+MED1lkrYRLUiEFUjmHccUoO6fF8BbdQwvD3rBTpAss1nDuO4BncCAwEAAaN/MH0w
+HQYDVR0OBBYEFFT81Tir0l9q5Cr5n47pDeY9pr4EMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUzLmNsdXN0
+ZXI1LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+BMhWQlbyMG7OYN7Xtt6d9sOduI+peTlDKju1DQHS0P+jvCuT46Tm7u/4A7G6ommW
+Bc7hLaaGi1gFyiR424FSjiQJg6ye5zdix09H6DQipzSB5GwfyQsB3YWsUniPQn1R
+ZSaqQvcuD4vCXANyo9LE/3VOJKqXB9sLdU42nNU4M4vyB9myTLTHodFoKuZwGifP
+/lv63dd1PQXfeQ/u5FtWopSDdk6fMigoKvo7f1SViTUtI+PmK19sOqOK3qyrCagx
+I0+krf0TsAhdGo1gwpu40JLb15pWU99IhKIAkAu1kjmAxrpkbztAH9wjCm1/jS+V
+nHe7wxiLzStz64Ld9voqPQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c6.crt
new file mode 100644
index 00000000000..35613a36735
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c6.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAMK8wla5/wXpbdq+VeKNBkL0pv6/MA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjMuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAI9iaWrpHwmXPBC3YhfzkVe10A7AKjRzdo5uv4ra8xQmVzsdk3lQ+oQD
+YMDFoP7rfxtRLzB2Z5l5rChFbkLav+3G8DJ09Vdzs28J9Kxz7N/H9tEiTmgvzdPV
+BWRyA7D2WPPiaHBeIIrtgzfZbHenyxuDxfNtvgvSgUZMEjM7Vg83AgMBAAGjfzB9
+MB0GA1UdDgQWBBSADI6qBveWvxd9C8xucsFtogIDRTAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMy5jbHVz
+dGVyNi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AEb1kIeYEWrqqCHC3g7eM0r7sCIvgL4fLNeWNLSMnECM2nBaDTpC7JQhVo+nnMKE
+hgYVZ1/Waj7LRQTR0tGZwRVXWKLB1suCszp+6Y3ZCeGR7ife9Nu+ZFucszw3IfgD
+q4DmNB/mVc4Uab7ud5BdpEVMLlbExlasiJ6pDMf0ql1MpWaRfV6pExxbeNf+FQhO
+pHWIzNk1Py/i2sTOOU6aWajQEY+2xFjlcdKzNFb0Dtq6ALsD6NuHnSIqAaDH9cAY
+LmMPzzBy7s/4HAO2LM0xyec5T4WI5+W2f2V9xpkgwG8gp/ypdABJfw4/WyeI+bpW
+ki8XWEjW63yhAUDTsAD6pXs=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c7.crt
new file mode 100644
index 00000000000..8b959721724
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c7.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUGKYfqn6eHAmevff9PPzxeULwjFIwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0
+MTMyMjE1WjAQMQ4wDAYDVQQDEwVuMy5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAxbb/mneg3oKdKk7tMpcpC+KDBsWWvgx9tKPqHFBWIrklLEeHVA87wuWo
+XVoEmoPRmaJkHCuNSUOmNUsw4ZAigdCHLI+Fxgu3RXE5YcOlR/VcfIdmeTOkZTmf
+kAVl6sRIPMARTeQkqaaG93WtXpSFQ+hO3RBIkJ3t3vTL7m7dUH0CAwEAAaN/MH0w
+HQYDVR0OBBYEFL/uRR/fiAlWZMNJZ8ZcDCDLLkCaMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUzLmNsdXN0
+ZXI3LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+r0hXtDPClFrZFUu8WF6h7kLwc2A1Dp3lFtYUrih9e7e2t9ANPMAfYbUN+bS/QCJ7
+1ric6GBn1cyLagWV9EyxoILtkd8lGkXUC9tuS3uk2roq9KBOFgmoIZ3zvWaN8dOT
+juqD2Z1hOQDUTYdiggONDTRXUc+PELS34571oFXq/c5/ZZlwww3J+Vxwr0a3N9LM
+l7hcobhUZIkFz1GFjU6H/64WBDtb81A29ZVGDsRSqsgZJECjigMZhmq9XRPjVSyq
+VK2bCg90lAIlH3408XZVXNahcpaWz6VXq4Rg2QAN9yES9u7t3qkL35AxLmCpmd27
+xp9v2+CIHghzMzboSiZ1Ew==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c8.crt
new file mode 100644
index 00000000000..7da427b21a9
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n3.c8.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAO4k/NUJiy5g41bmdZi+G1mdw9DWMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkw
+NDEzMjIxNVowEDEOMAwGA1UEAxMFbjMuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAIr6JyOARsRn4zJ//TSQ3eMigJDnDTz4qloEcGRhdsEmEkiVxmawSx5X
+YZeqvQIz69axBViHQZEa1emNrgktmzR4swV8wUip8tJhcic7iegSYk40VG8w5YSD
+fVhCa4JEjTF+H/0B61j+Gq81Xzqw6g4m8kJWqWCvICNDo5SKkBSzAgMBAAGjfzB9
+MB0GA1UdDgQWBBRYXtwMkHRZ58jOv4Naa7AkihBRijAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMy5jbHVz
+dGVyOC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+ADGVl3fvVGFLIRBK1+qQK1LHGkGrNpSQ3R9q7uDSHBIP7YYp90SF9mwNah+Ma+0e
+ZqkmpD85QyzYas9lbXJebE/Mp47W422xwbVqqCqU+w7XMpLLZUbY8LM0PKyuepJv
+GETzjI58H2Z9kU99xW3aQ2dti8UcfBeoOiFJgWtyuI4uiqa0u/5+by1uBVW0n1Cv
+pyZD+bWfFt6Aoe+8xkQMnVZSTlfTfgpUzWM8vDmNi4l2cSOUHa39zWmWRH+QEl64
+EF1rbGwxaYEZ4/8JAdmWD8yzjjUtmJjxjn6PpLOQCDkhTySlNFApB23bShr/ABD/
+KyiL0JK8z8EBOkUxZiXztSw=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c1.crt
new file mode 100644
index 00000000000..0229d50acb1
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c1.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAO20mZ8U6BS1TKy9C/jR5Fiz5Ey4MA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxM1oXDTQ1MDkw
+NDEzMjIxM1owEDEOMAwGA1UEAxMFbjQuYzEwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAJbrB0ic/oGENs1JDhRT4o23j3AwbeUE/CEKZqwHUIavjvIHcD8Vay/0
+TpAJrG6EoriqlqNN+m+Bm66NENnyuLsj4X3q4LyX3WwFimQt4LQkssfv9+q1kvac
+UgKyytoZ3ummHI4bhpYc3Bq4SrOQchLd9EZBCvURMKdDPjxsaAJrAgMBAAGjfzB9
+MB0GA1UdDgQWBBTLdAFCf9QVjWvJ/FUvgZl8vxkmGjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNC5jbHVz
+dGVyMS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AJtTgYL5eBaKTYNEWgehivxg5a4uV//zasVQHt6DX1WfJO6mYuDQl+OTdwjgKPKz
+m2ICAKjZ2PV066hzazrVULpjgMaUeRNxzNJi/5QqiJorNSsFVwSYkMjDB99KgWPf
+22QTx0mV8141lUZY49iOnLk5u+h2tAhTF9U+S8MvXha+vyKc0SQpJcFurNxEZZvc
+x0LCfLDixW/xs7QcfiNO2/Jn5lQf6hIOkyOUHRfsGs9QXlPyjnhvys45+CQb5Cve
+v3vEDnE2lRe6lQn2k2ZOWrL9cyYfROcJfQLfzoKpNdr2PaFEd1g5Sthznv7KrAQ6
+dHr6b9xgGbf9I349zliuhnY=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c2.crt
new file mode 100644
index 00000000000..38c9f20e351
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c2.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAIIj3+gGiW2qnF1Y0DJuJBBFfM5MMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjQuYzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAKj0cnL86BiN2VBhvrH3XDplcwd8lFAGxAzAfP+Sx1Swqd6y4hZoX2Vk
+J43AuYvJY7aoMK4xIQJ4lWbrvCa+5epbOY1GGg82Z+/Od7mfZppfajCKTAmAIXfa
+SW48V/fRZyYl3KDfP4h5AqJV02wAJ4g5r7Olm74dwAMclLF6FqwfAgMBAAGjfzB9
+MB0GA1UdDgQWBBQ9SpGlYooWMcJYNuTND5SQk6EPfjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNC5jbHVz
+dGVyMi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AGtA9aht6J9uVrrow+ks4IxvSTeDK055rdM1ryCkszKf/QPzsDfj0VONEjJM2GhE
+Wib6KjYz6Lki7mEa6DY1IxPZHzMjjkfeLYmnE2+zgdGH0X5D1bgO7cK7tWmcuVAO
+eN0YxO67av/PZT/00wLYva1ubH+zY+C5AZYOxJpPcJ8JNpwO73UDFZwbnUzvpK6b
+mFN/eBqvB7XWViJcHgoXEHkYH9Fetnpt8T6EYxWDL+FYi6iN4/L0a60l+emeleha
+fcbjwU5Ax630EZAEecRB1D2wYxwOIFk+CGLeXpT2bSgvtmfU/pIHPeSJ2lSAydui
+bVeYBdRoOZeUpX3LXO2YuLg=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c3.crt
new file mode 100644
index 00000000000..2a75d1584f9
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c3.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUf9E+9p3WuX54FsOh8veaBlZx8ZAwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNC5jMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAlLG3qMUCPi2usnc7jsxRFHVGjbf5+HWY9nWaboIQ1vHfn0Z3m/hOOCvx
+waNY4RF75V1ZSeRsAKzGeDD4NC1KC2Dxa81elMfbXq6nLDIfh0klkK8lSw6snzpe
+8NDMSJ8agNdr6zLUgL9e3qh2pU1Fc9ApR6+HRXA9rcnqp/xm4XMCAwEAAaN/MH0w
+HQYDVR0OBBYEFCz38GxHKudMx4dyBlrAcIB+8XC0MB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU0LmNsdXN0
+ZXIzLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+PvCi4fiQ+711I/HQqE1YLGv6Z/Fys39CV2Ch2f7VVgb0o2O9UVpvs3UHxHwNOJpt
+7l3yap/x3Av8lheE+w+qwlf8M+JZMrdDkMxevc/sTT1C+Pq28uet+RfaOdDulL89
+/mFD9LP/kJUhZ/nH+/OONWJ3j3oIkniMNZ+fUktMp9b/efDGD1xb6BDqfOS6JJ1s
+NA2+gncc7uOkPZzOOq/cxZptlU5jN+EFu/o5RHpkjA3S6yQBav8SgahDgRGeorUn
+WVaOiv1OdX+LuJAfZbGgOOxBi43zKT/TDhITcTTHCjmNKX9rfP1lrUR6lmqmFlwK
+L9pdLHQ/cPPNgWa8C2Cffg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c4.crt
new file mode 100644
index 00000000000..141a3c9215a
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c4.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUBKLSOiGqfamUa60JiTDMc33jgg4wDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNC5jNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAkPA4JMal7nY+H0Rcyr5Kmvu4uL6HG0kWw1XLXq/ORJ+NoQqGJ+X3mJ4F
+HPHWb9l6yfumutK7HTSUx6voZzgFVG1OcZ6dUakffCkbjeoGVe+4G2ojlwfvjQrr
+JhoB6aXJLWRTDY4VrNOgijlBzYwyZHFF4IHLAWD/8u0RCGLdiZsCAwEAAaN/MH0w
+HQYDVR0OBBYEFANGShToR+wz3wlqm3RqJGVNkBXvMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU0LmNsdXN0
+ZXI0LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+Tots0b/0b0tceD8D6XlqY++Qg53berDvwBjEu2ntMqlrXh4r7h6fOr9pmJ/Tf66L
+VJVnYWG19uh9owI5pO30/C603N33/hAljDvdidQZsaKU1KJ4Vun09qWstRF8PbZO
+4OxTzAblcZtHs7DGhKJL+fovS1k2hz6691jfxFXXls3S7asOnFrXoCDkG3aGvvNp
++HfygNewAQSnimKKzzYHbwqqhnXAPQbI2nF5h8rFtoew3sd+Kdh6GTqCPZWntlCX
+hEG1+MS17pms3DuiJt5TPsZh0piJwkFksbuzkYEwH8Hg9Xvi/0ztY7J9wrCqicUL
+r9j1FaOwi9QlwLVdFAEQAQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c5.crt
new file mode 100644
index 00000000000..f0e9b704cb1
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c5.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVANsQ0wa8/+5Cod0nsGdhVVTxFa4WMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjQuYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAKCP9rT1CKEdFPbGE2ywJgZiX1qf5H36DwokH8diz/XVk/t2QOU7Hqui
+5HJkQ6Du6ywPXOqAIg/Iv3Rj1Vo+B9jcPs/DY0Sj3mKdZHhySaoTHPWjv7mVa/PL
+fMElbmB4sYkgfotHVxUir3Xw5byGkJ+SjG+xYrMOSktBNph4Zh4jAgMBAAGjfzB9
+MB0GA1UdDgQWBBRrw5xcRVozWKOs6ZHd4Q524MCFyzAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNC5jbHVz
+dGVyNS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+ABG0KkEjBMa7QdsiR3Fi51gX5w4r169yXmkh52nYOKw792zI63TDZ00WNIMAZg6y
+PG47XTbF2DHGsAuPbWYTDO75SLJT0f8XKAHpw8TIdv+zly3CKzXN/94R1W1HNUuM
+lTSy3gbGy3u6AkZXivbtMNaR2loBGsMAQCHDM3gmi8PYsIaL+EDekMUF0NbiFyBY
+TVEGYERzvU+ftXryGn2BML6ODKGGDcSlzTQb+tSSC/+bfoaouYUcvU7DTHUpHE3I
+f1RzSC/NRv/gx3HKTdlpNNUNqIANkyWgtKMBbzOhn0SkAlIc5Ap9QBYDIZW96Aj+
+/Vn5JlqUvvdbtbBbEz8+zyA=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c6.crt
new file mode 100644
index 00000000000..797186f4723
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c6.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVANcbAqZT0PhoeOyE4LXgFN/20v+RMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjQuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAKiyEVPmc9H8quSkeyFE0GpA1yuRJfDd1OJ3I+ogifTkmZcKu3u1wCbx
+v675xRdpRzCbB8+hUr6ZC18qWUDxXp1ml4iRr8n8bVAmENgJzzp3RLBZROFuwVe2
+dttun1SMiBlnlcUnmSCX7OCTJWrr3tI0/F8RIdaB+63gf2Eby2eLAgMBAAGjfzB9
+MB0GA1UdDgQWBBSg537AtIe7R0hQVRHdpCNBBw4I2zAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNC5jbHVz
+dGVyNi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AC94yZdlaV+HvgSBn/uc6cDYBXMqe9tW1ENkEpUTYl0Umyy50qxonlsTvZijKB6y
+S9vcnvUMs8+AOGPgwvEszM3qY1R5co+Rl+CXI0sx2iZKEeyGDxAFDBldpGaOqV7b
+AXKeyR9SB5/Kh8XZVyxamtY0iWcRqdc79xljkZZ1jl3GbhxkXPGtPYYKCwh3u6hB
+X4cWgBD0cGvDi4yRiHI/o2ssKa4DGZIMKx3Y6aJ10l/7cJ4cWzkOaEc1RsUTSPtk
+MTkO7l3wt0VgCZz3ow5huwjfKwQgKGsLVEZQiLJLCn6P+veo0jm6Bf+pA4vVKWE7
+fzmJuag5fMuoc0oQbt7BxWc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c7.crt
new file mode 100644
index 00000000000..435d12979dd
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c7.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUU67LewM5UhpCYrMabvxZrdBHhCcwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0
+MTMyMjE1WjAQMQ4wDAYDVQQDEwVuNC5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAjvRiPU8N+9dppeWCZf3gRL7r2afS6iS7YZn3yqYeikXec14GkDotYxR+
+ZPeG3iTwhE73I+iXIScqZmtqk6sL3Iv5Z700w8CBIhLFZP0L6MPDpT0WwBweRzC1
+BA1uXam3Cwp0hux5xAH49h0EZvFT6bxSVdhrunsWlW1N5vZIOlUCAwEAAaN/MH0w
+HQYDVR0OBBYEFEMbNKUNe9yyOtm8R/QonVKFl7C9MB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU0LmNsdXN0
+ZXI3LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+kIqfKAq278AizLJjj0tTC7rQTlHRMpVSdzQUfdYR+IZ6d0AuPe3drBKEMLsXcY+r
+OndzUU4YVEsq+OVZcjdPsVW5FH7kHYzQsbxDTPujQgn5ED3ggDGobWG6di18hpVv
+S3Nt7iWN7jl2ilXA/S7fskRH6w7mVjiRMsV8QiwwOtTkj8e1vQBa6l9S7vHS2vFr
+U+nbTpdVrTKTZ5+n36KtmqUdhzmp2V3krVCihOF016TBzU7tp3+I4FNUaCLj/bsC
+A4KWacL0cbZul47Zd4cKpFDDo3PxSxDeBgLh1CDx4SJaKcrko9YRJ4ZgA33GAMAv
+n6V8wxMzyGROsR663RIySA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c8.crt
new file mode 100644
index 00000000000..bab6fccac64
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n4.c8.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUZPtamUFGkwEsTdz8nVPsnuVKmagwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0
+MTMyMjE1WjAQMQ4wDAYDVQQDEwVuNC5jODCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAnUV+seRzu1C0Cunk2tXNWXVKIc3Ia1PjZ1ihx5diN8KsqgXzJPtVl2BJ
+4+DIIW8yUVqera1P9AcbeQo1btzPvAr5jUFIFAxZI/N73x0KBFK2rHp67RPUgZBn
+f8fkNrh6OiW76Dyj8bd1R7PyGrG6hzjW/gkEA5UMY2Uh1hKUak0CAwEAAaN/MH0w
+HQYDVR0OBBYEFJ9cx8fxd/vOjAM6gIQw/vqIC1gGMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU0LmNsdXN0
+ZXI4LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+KDBvftp+20KL77/gc1sPeViQP7SzYbrL+lNggjuBIti3s0oD5Cv30QmXe0EqpWnH
+uK1BtlNu6JZ5izuDneeVVfscCPUqgzjrDPCdFFHcPBPlqcNlUBdZtsAvq/pXCSzJ
+oyy1qkqu82oOhnaYKZVEUdtm7nC0lu2A9TMMQHgGq20GOvLMTxZ07FsYZRrghNRV
+xUI/YLZFaTyEGIdd0hfafFXtmnLjBJvevgcZ36S7BARfw6ZZ+Yum1tlqKBftVTD6
+P28A0nZJbPdVDOBfh2zY7/PokAaIziq3cVuoyOx8ti0kPhZJiFSxjWSo2Guz9jLp
+fUXqHq3QqRdgaYLt1YCn/A==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c1.crt
new file mode 100644
index 00000000000..ede8be0a273
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c1.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUKdCyNvk9xgVTDO9On1JBBAJgLEUwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0
+MTMyMjEzWjAQMQ4wDAYDVQQDEwVuNS5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAk2afL9SKZO/18apqEJtcnVn6j5KFVgiwLRnqDe0O0waKAuAatUkRu16E
+TUQiz9gUJ3LlFA/7+A+6pBwgVj5rh3iheQ5/nn34OSP4aVjwMMcjFJgUxPVvRxR1
+pjspxKBsMdwTt6EXBg7yJTWI4Lk92I0Wy6vb0JAf58syQYd564ECAwEAAaN/MH0w
+HQYDVR0OBBYEFHs9eLWpbASF22YffoTchou3BPfeMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0
+ZXIxLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+Oz+MEYQX8+5uRpJQWkdqw7fsmRUuTmfXSayz09SPQ+jF69iXTa64PvEiKkeaLSYX
+mQKNNKpeskYKdGQ/r/fBFo6FRLLvtFfLfGC1OoOIZxFy2y9+0MYroEijQB9dASeh
+L02IksNsvPZnOMvMitETDoQPRK3mG4OcFbdvWuZa8oBJ1cbHqJPngLaUn6PRc75A
+j2BvbeRLT2OZf9whBfLpE5gI8oWhTUXnGps2xKa/368aWr72Bi4/sMVMLCQkwxxP
+cwbG3GKF015K1Q2BgfTDSPnbiCXViuSGw2opCoflVlH8qTcukxCyrTiOmaXfdds3
+qB2TSCnpAV5UehB2XEoNyg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c2.crt
new file mode 100644
index 00000000000..27b65a7a592
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c2.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUDQRkdVBMn9YP54iLThtM+V9kTEAwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNS5jMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAwIe2m8DEVRgwTgfukT218TRvgaJ88GO5v12NUIg/uzgq2ADAIS4lynhz
+5mzsdhcArzWFCz7MxP/fMxfwzRP7dNm2pjz57+DdUUSpPrBCDL/3+JwHWevd6LgM
+mgLOSohsJOZmWe5PUVMiP8/sluBb1+63v0e3iDNUXreVal0xxF8CAwEAAaN/MH0w
+HQYDVR0OBBYEFOOs6r9usaTHZ735J+HCRsZb8mDmMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0
+ZXIyLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+PsRSE3bUNMgAx8goznM29Uu8WzrsA+8yDd2Ts/Cjj928vkT4xLiOOAGxnNpdhB+P
+9ii99A1bbfacXdyK6Chm95DoiLXfKZusHpu9C5EvV9BDQJDEqHQbf3LUGo7Pl55l
+wdnGBvAmNcAHZ0mZhvm7F0bXBPJ3beBbnjrcJGcL+99x0SwsXYeeLGFNdUft3nA/
+wYk386vX4h1Rq0c+aJkNey9eaf+qUMfClEtAX5okjIvxT4sETd/w2gB9tKldMX88
+0KkwjIk26HqQb/TYZVX5rxrP11Pf3mzbWI28Fnscw6ewNRQr/BWAY4p650MJ1dar
+RLQGA5ZR/1IBQggTer5Rcw==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c3.crt
new file mode 100644
index 00000000000..89c96600569
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c3.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUJr1hlTc7CXDlsSooLb5/05DMugYwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNS5jMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAk4EUO9srNajozMBBRVv23wKGKGQQaiQ3w/8x1SSDTsIQciJNIsyPQW98
+f8lXsThi2IQtRjSCtNxZGWftDRu3t+4a0L3tPEvrbt3H+OK5McIbS2SjhsX8rIqJ
+EUY7UJtdDm1DO8Oibn0U1DOTTsdPloW3zk7GGrDo6bxHpitotyUCAwEAAaN/MH0w
+HQYDVR0OBBYEFOUchU2n+E9rdI9UjdT1y6xrSUopMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0
+ZXIzLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+DLA+tUvoBH8QkdHqpcFWMxAU1pwBN4dFh48iIKeU6tlxBZJ3vuivUwvUMZ+DdgFA
+QRAkmTuBm3t0WnIukYO4huGT67C7nya90wSyghff+9ef9DnqVvd8rYg0S/axjaeG
+tYrDI+qK0GQWF5wddskzpFfxIaZzgeppWB+CBjgFpntDOFql6L4jbaU8rv8GtpW8
+zHCFAF+38sqI2iXD6njZPjDSN7aYcYmDutqyeAB8ulRJ/q3lAK95kawp2wMXX7Yx
+Lz9CrwenfQrVVVpQt6l19zhZQs/Hu1WeDvGGsicxwjq+s7fhBr5rjLYqpUSf+SiK
+YCNk5fKpE2CNh8b4yalySg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c4.crt
new file mode 100644
index 00000000000..4f6ac740cf2
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c4.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUaagjAMKpb7/8mdQov867WsLAx3YwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNS5jNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAiGKK1GCMeyJzrzzi4pNaCWqd2qiFPISAANTh+laKkKQDLbrLo6BNfv9E
+f2ZnpFO2JXWbDzNd2UDA5wKjlNPacFvoWbQM+pydH5KOmQ0tG5AkrWgnMSVyZ4UY
+7tUGAnkMe7ZwtWWETVTOzW478mqV3TAM9FjIPmUFuIyR40hF7EkCAwEAAaN/MH0w
+HQYDVR0OBBYEFI+J3qFQpd1bJy1q/oww35Dt/lB+MB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0
+ZXI0LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+huoeSFpQjEl5VhTgPQe2Kh+O3zjNTIGUXV4XjSf4m1hR1X5InTjEzSVrSwrioAve
+wRRJZfQ33tN9RlII+80LNWozQHMs7MTTPMpOOAL3XcOTUpIaPPEAye5GLfs8hsM1
+gYluFjoKbswkvkgHR78XqHsifsNdABSaSn87JUlP8TV67GkYTzitXwmtA8ZhpqFi
+J3GdoM3t3OwhkJYdYEXjtfWvlzQovlj79zP9NCc32/K37JRLkynzUUpeic5dIHGN
++Cs9gV23e/kzpHOVgMq8it5h6Yap6HI2XeiRUZfltB8Gm4nQxHFPkuA7M2X5nfXC
+jkQ5EpEs7EsqXazTAWauCA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c5.crt
new file mode 100644
index 00000000000..8253f01573a
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c5.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVALC2GLx1iArQPLmEOTSnU9hhJiiFMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjUuYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBALttwAoG7pVbxG29TtVi8YYvfyrw18qj3pIwvTH3uD0NsqlGqEdl8Sop
+mwobhEc279RoLf5rA54KEcUaoEjPJo0eCPfGIQxWOtSCHi/Dpp28o32wFzj0uY8v
+qgOlhY5akgRQyJXdgHBSVnaxYbHatPgO0P9seGLkpOPEhVK/mhGnAgMBAAGjfzB9
+MB0GA1UdDgQWBBQd5etOJglTebjjwgVm7DnZovWhBzAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNS5jbHVz
+dGVyNS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AK3qV6LeIWj+CMsy4qjHmC+EbXAUUS0Pra6aFrXBxOZ5t7h9aFEN3zJjqTTTl7cw
+AbS1it93Tmr1wyuIiZ+dCtCr6M9wJE5vrKpe5rEp0tdeSs5pm0OkXPJVU/2xihW+
+NYRw+oV7qG86ldnLO067Tgy0DLPYP041gJYr4HbCCOjPLSi3B6Kn0PMrYcvPdqmi
+lHGqvzqaMXq9dWYD80PKkYVOUwwxYzZ8sjOWAE1JXCVXI1ImGh4yFZAArKsY9uEl
+7scQIEt0emutzHaMLwiQx2yTUjttHaogaa8S3PAHNZq4yHHCrD6a15Zpouuz4EdA
+s5Dd5xbtE6zBBjGsauInD+s=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c6.crt
new file mode 100644
index 00000000000..8e4cd6f50fd
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c6.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUOLkd6HCk8li8bYemSJ2y1s/7htMwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNS5jNjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAxUpbKRNQ/WxzJj7oYFBzeP3/JwtVTaTqlJexfKpEXAGlTXrUYRVyZP80
+4p+2Dc5sAFEFXwUcmYgVlLCj+mc2OGg9Uv6EyaT1Bz0r4oEbIB7ePBiefx41i2Rh
+d6zy3Jg164hGnrHzmOdqhz0hjKxUAgBFzEtfx0URtIpscMefimkCAwEAAaN/MH0w
+HQYDVR0OBBYEFEyrP19EhCIvYsJFVyZPZ/2Uis/gMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0
+ZXI2LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+pZRghboAl/dWnrUXB5Wp7Bigbpom1KPFZQ2AYyEs0RF8xH6CoAMEMZsXDm4+sjFi
+uDfFoXVNORrwdy6nsu9/Lm6dC4Fl2got2B1ZRT+jjpGXbJmPeH6gjvylqo6xopJ8
+kqozuLyLaJPenuPe/jU7VZY7WTJ36LIQMq/hCf9RVfD6513fGM1DifQwhKK1o6Ms
+u1GSveA6wXUZCqfkbr3nBikhgLQP372dF611mrLQBL34xDqDtIfGeZ01wc/omKCq
+UfDYh0uwJXG90TlM77bjL6LrRP6rvTff9pnFEENqytn39slXXahGoDos4WnU2y8F
+hUcosMm84zADrczmErWI/A==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c7.crt
new file mode 100644
index 00000000000..a344076342f
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c7.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUXDFTEo12oo6+EKR1kSq5mxjGqq0wDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0
+MTMyMjE1WjAQMQ4wDAYDVQQDEwVuNS5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAg6EDuwYFA0XwT9/7mMHsHDejJrfDq8dZsYm094CQDcddBa3DRxHuHvlP
+HI+2yNhrc+LsIXa2xXutpmFfu1Um3BWrnvndOkK0FU5VdyNeFdH8eWjT4QVVr6Xa
+I586qIafTcLAgt2k01pvocYhAYd7fGyTYYsbW4wjxyXP26jspG8CAwEAAaN/MH0w
+HQYDVR0OBBYEFCRFQmSe0o8k8hohFXJ1FtB4A9QIMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0
+ZXI3LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+CQJWjpCXPAEQcDcv2pYKzSbgwO80qZetTcWXSzx+dosP3LZZqkqv1EfPm8As5wm7
+2qeaEmOzrjsAajInZUzLwcfTBo7MqlodlDN72S6/kOkUe/Q/4M9WRl8elXf6D3Ex
+tj3X9dUf5bUj1cqeNInAluOsj3ZoYlFceo3ng3berAjgMxMjqnJi9O7KxLvsTYdR
+fX5a3A7KbSPjlnP0/n6FHXK+cxqysmv4m2TkL5Dsn3jK1gGJJz2qdUjiKu3jR0hR
+hDsyiSlVVgqGVcTWyTa92lAe0KsosXR9eTV6qKwXFKA0FKDlPvVtp4pelDVWdaeh
+QQsTs7Luvaoo7xg7W4GhvQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c8.crt
new file mode 100644
index 00000000000..d07bc610f1e
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n5.c8.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAKEAVAjsgY4Ft4ATYFfKD8C11yUNMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkw
+NDEzMjIxNVowEDEOMAwGA1UEAxMFbjUuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAIJQgqB0qJj7Db0GiPnvl4AsKtFa5DV52/DLfqri1FwhOcIVhtnLXFA2
+wsUT/g7aJ/b3tZszfTwG0mKSmNS9voTlpaLAb6Gn+vq6bBpgvgW3kvcP+r5lxMIG
+U0zs8yC3hqXwUOX/FbWZzd87eEiM6fDfhwg4JbP7nSk/JX8MUEqLAgMBAAGjfzB9
+MB0GA1UdDgQWBBR9W6ltaRBtK+Q3dWeXPFp5cwdSFjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNS5jbHVz
+dGVyOC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AKopACutziODzeAqmRV1qNb816EqKoKdV7KtsiopOH4K68+VALvTJHZBHHk5xsM1
+LvWFvjDtd5zH2KcLz+Hqq9fGBn8OWgUu7CK+S/rbMLpM6eM4O2UpsCRnvXvWJrnE
+Xm2UdW+dVIM1do1/tebMRJA2KQzZExRlWIz+idn+lUFxSW7BZM3tLOQ7RgAuCTcA
+F7zFjCQROi9PnIyCNHr2TGGJ0GiJuJ4Lovj4WB9jA7e/bYPJzbY2zp4cAuIFBZZU
+rbUGeIJCvY4jEyV51KfFXXJVMmCGtrtPA3GNXeqhS9ph/FDftakMPTedx4Ah+hL6
+fhSR5Ce/PvqTW9Hx7LMz7qw=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c1.crt
new file mode 100644
index 00000000000..1c8ba3354b1
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c1.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUFpfeijJ00JLPz16Tv/3R4i0TQFgwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0
+MTMyMjEzWjAQMQ4wDAYDVQQDEwVuNi5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAkUdwEbxEusj+J+9qllbp/jYccER/dTYUWoDClkxfwgNUN10Xs5A08ERS
+s1DZ0IVfymRwQlyeciUY/Q0M3gkRXY3vU2M39ZPAEWgcMBezp7VopotG/4fPnGoh
+21vlB+qNu5CwcWgTcdWtsNmfrSkQ03okWfd123WcZhqYxHJxL/sCAwEAAaN/MH0w
+HQYDVR0OBBYEFMsR/lNScpkcl9QxX8JAMVP7mT0WMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU2LmNsdXN0
+ZXIxLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+hFQp+02dHbsLFZs0PeqWDb1Q4iB8+0esIl/GaH9YuEADxjDaOGT4eEvWIC3M8kh6
+6v5OEJO8z43y91EWJdqzu58mF51c/18u6paC1EdkO0V5xR9TT/AXgNFzoswmlpgJ
+G4CI/pKuTJlPlu2zdf74/Npufl3blx6UNdE705xmPmfS61Ws+wm5Q2qGKF0IWlUM
+98OVPftL8MLv29ODtD4RlVe9d9WLlNZKq+0WoIG0UOOHaBaAyC4ZeHbc1LKW8m+S
+hlyZjc1E3p9epCeZQi9rT1xPs3kRxsiNnhM4HVVtmiXmhMDoA7sO9A7OfYrROpLm
+0V84QIeyRw2ArSh3si31cQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c2.crt
new file mode 100644
index 00000000000..0380402e43f
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c2.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAPzUcy0n1Ww7M2AliNfADZ8oKBhpMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjYuYzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAMJ7+brk5AZGhtD9dMKVhkHCmsAhULpd94aF8nK50Vw/Jgf/SdE6yYeP
+rBxBC+Or+o5+N8Dwe70escEOH6o793gg8yBWyL1AagoJZDV/+A41cxropz0jVW5X
+4SJu+y9tEgVA7m6cdefow1SG1EiMLMtEHyw5wKNmUKrl544O+MQvAgMBAAGjfzB9
+MB0GA1UdDgQWBBQGIpG1JOyVo9JCyp1/h9yMhHE3lTAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVz
+dGVyMi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+ADM6lIy99jbMevqPYHqxVhbCnfXP/3+amzXOn6OUGme6pXkfZod52CGjXeLSnEsY
+OTwMAlzpp+ghdNHoig+ZewyBsSimdiHU25TZNAuOIFHcAvrX0DPm3zVqnmwAa38a
+Yft8UdcGJgN4oFoY9vCgxiSmOgF/hBHABmj7/WO4tHiM2EZzBaOJcOeGaYe1e8t2
+z9LY3mbtdUJXZktB0e0MVFsHT1Q09+U+qnJzXWoZ3zVeJkcGt7E9RUyzHa54qFfa
+II1g9+BjWg47iuWm15W0B0IJSZqeTcsvTtxSPbX5Y3ym5pcWZ00IMTFvRlLaLPQB
+e2O1dfbp2RJd8ozmBcI97FE=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c3.crt
new file mode 100644
index 00000000000..8ea16b43baa
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c3.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAMdfglCcL1l4qotlEg6YabyONoRUMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjYuYzMwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBANBW+tmJaaum3CPc+7wj+qrDkbvuDue24I2Yodp3HSsChx94KmFDYhGY
+uRWwsDF3Cu8iPyUi1xk4fCQallLCzkwny9j6dljAHtAYkVfNP07WBdPJ79IWUn4q
+bldqLTam9ZiaQZ0jPtHa6PUmj8doc0QWM1ySfJcHqCP53GkqpH+vAgMBAAGjfzB9
+MB0GA1UdDgQWBBRiy14zafEFR9kFLpd7PeVFrLdKUjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVz
+dGVyMy5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AJOOREHVw/nFyC65uY+iZIzMdpcmKKWdLwaOw0MAn0ru9B9m2qGT4kwCX3m3D3HJ
+53btTyvHa/URXjtoIPL48VOt9qB30MPAyjQjR6C1po5DwBZHVWMZ2QJXq5RBol3M
+wamYq6dgzyUxWYI03/51az1IuU9N4IS2E7/HN4YVWqE+CPNroh5kvrg85QQuiENv
+D8NfxYYshGJa+kTTuLnkyz2EEfVwWeI8+7x93/tXryZE1b1EvNMxkl91ZJbtg0bC
+Hb/v98RCddP50shEgUxdMQZD2ukkzCabnRGmjuLsvH9OtsrSqCoi/0umapW9wea4
+fhJ7Rt3VHnAkpbsvV3jOx0M=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c4.crt
new file mode 100644
index 00000000000..45168d7a670
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c4.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAIwepFjviZuQeudI1+ErlWyWbb21MA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjYuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAJDY20sl1QeuOSxilJdb2r8PygM/o6EPlIJk/NHc6Lh1VG2bxqsS091j
+Cp1UY5uHdynMKXxVhgbIG+rKHgP67rh+3dTWzvThWDMZ1ljMMpdf4NNH3caM7Wdg
+Pzj6FpJbuEevBnNp9ENRjKFv8DxUDiJPFsXcCZ/sGuK0HUZSzla7AgMBAAGjfzB9
+MB0GA1UdDgQWBBTPFm83nd3zU/X8KaQpSIF8w8njkjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVz
+dGVyNC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AIsgxyXgff4XN3ZuhybqDrxKHvMOOOa7npzqODO97/oZ78+Xs2XMbDSp+ruYZylt
+AMsos5FzLydhYESKE2nrrMEUAY+V+mryNGX5lY9Z0TvdjyA24uVVBMSE+R96Cm8G
+UUP+ekbou3e2aVYKOSyaHL3mwqbmo/CB7VkzmOxzcCqVMB4Oi+fD5EQ/qqi3Bi5C
+FNsYdelnWQ2WUX7pfC8P+F011WiM+HYo5I9hhbuqf5/ALG3CRERKZiXcMLTgFsys
+ckjB1QHLVK7yFpiSdUqqAZb4ZPMtP/zr9YjRwyMRH7vDyyQSF6pQm65vAmT7+h00
+FZUilhJHYxVDYGCJ/AQXVyY=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c5.crt
new file mode 100644
index 00000000000..b4a07a31d65
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c5.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUAOAVgCzC25AbALSA7HijoxKx2BgwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNi5jNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAgsoBkvyRXFYOH/3/8AB4blT80XSJAFKu7L/zH4IDbLNXqah7xXxaii7s
+AfeSyNOmDw3JZR6O8LZZA/52q+vf63VeEC5R2lh9xFWDfNLiYVyDYoau+dVy1el3
+tev8vTcUgSlpCFSzD7Eqt3353dXFAzEXI1YAeEHj+tEipY2N+HkCAwEAAaN/MH0w
+HQYDVR0OBBYEFH7CQtBFpWcATKjoiCf5b/jy0mlZMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU2LmNsdXN0
+ZXI1LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+DMqOMi8l1GzyZK67fA+Q0H05+dBGByALXCagAbso4BayA1C2QH8/cTShEHYSyEUC
+WSm7icucMdlyuxDZ7J+Hz84p+el4IejcsCUKNPB/pkWsSt6xNhOxeeuaoX9DYkt1
+KQL2nhHRP/FgrtH/nippMOaz80GXnaIXowcW3qbL3RCa28pY58N8NkrX6AtQfi7h
+UofAwoC/S/N5qVuaImZiqXT62HpL/reKbVaZ/l0uiHdHrlnIAcgtgGM69c9hEOaz
+/W37Ql43n4F3NqtYErCFZKtjuDIdptt8YUGhwhG++ZGMhQZBGKsc8g1OEG4u+oYR
+OVGs/kC5nfp0Nhfiuz2q1w==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c6.crt
new file mode 100644
index 00000000000..0b4eb677336
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c6.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAKtpr++icq5uRPMlFd/HaLlFjtAWMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjYuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBALAFA8o7mX4GYsexgC1JaQzogoJzVK0XGeeWUMKIU3kjhfjezxwY8Pqk
+1bCohm+WTdhRUxtO4Ku2AMz7FaOYnhf1gAALT87M8iEQD703Fd83jcmrAuWG0zib
+kzos0xxzOrg+yMU7Tj3YGBqDKuOiXR9vNR5vpscU81bg4ZTT561DAgMBAAGjfzB9
+MB0GA1UdDgQWBBSQZ4R1AxlxN/+tAONyY27r6AKU7zAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVz
+dGVyNi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AIcqrPNc1Yr5f9aeW24lw5pmyH7sUlfCW8O5xyL4Kg1Nr8bWKFQBoWjeCL/5kMD3
+/yrQrYZRCMMNd2Befr+otqe1ykuq1l2fpn5BNLTDlOui07MLuvHDtpV3qUOjPL9p
+ocemCoHz8e3LITaP2/s1eYf37p9zJpyI5Lw2UGHtvbWZ8uOS2yy50Vlf28WHAETK
+/BoE50TjQ0e6/eMxammm9TkC3C7z7m7NFJ/421uyy9Aagc2LibEihD7+H31mDt4r
+X3dDcaCDM8K5n2WiHlJ3ioB8cNdnZjrAQUDJg//iYYLUzN9tH0i0HmPj4Jah5JYS
+bLzwggw9Hfc7gftcBi5UAFs=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c7.crt
new file mode 100644
index 00000000000..1cd5275e268
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c7.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAJkbTDOQxMn77czLVIYYso4B2oguMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkw
+NDEzMjIxNVowEDEOMAwGA1UEAxMFbjYuYzcwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAJy8A2khQkFtzq1bi9E8sSKSrJ/v/sWAVASrv8qwuiyRh0F0sxp6KgtJ
+4ogpiI5WbhbIoqWqjoDwGgGvcvf24m+/sr4JDdKb/ZyzkKGOLhLXugQwZABOCPf5
+4DJIAs/JqoxQ/XhbMPhqLTz6x7qPLj3Tdwybsbj85nZyedkx3gyBAgMBAAGjfzB9
+MB0GA1UdDgQWBBRq79jvLNS4zDUaRG5JNpPgOqXlWTAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVz
+dGVyNy5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AAU1INEj5h7Z4j7GFgwGkmaIOJhLrpFcurqAnrxovGRm0MuSvFSsdORSvRW31Ck1
+f4U/ee5emLhkv5rieUIPoWmJH0B3f5YCNb/TTXJXhD3XeLhz0vsd+UtduT+EGa4M
+V9t2l10rTAvYa1RY2FOsof1UtNblkf6iKynBYO9haz2EoYCE/RGsJMFIComKoXhu
+s6VVjehIlT5kDiTOBu/Dnz8Ol5k/Cx+KAvZJXaPEpLsXrzgVtvH2OT5j6IG7B+nF
+LHzvHuKm6EkgisXqP2taQx8SuWL1twjQbxl2Vjl6UEI2QtY08GE56a5JCqqFxN2k
+hTzjW7Iyyv82mMfiuLb297k=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c8.crt
new file mode 100644
index 00000000000..5bd70c6b909
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n6.c8.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAMmpIJnFnhv3d1sLi5WuoNu42eN9MA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkw
+NDEzMjIxNVowEDEOMAwGA1UEAxMFbjYuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAIMcNI3+aYOuGJx1YVq3VntERfFqmnAsssk9FiJMCzbBG2yD+hPlrlGc
+CUpGfTBzGEpvdd7ftSoy+2SJv2tercjCkg1enCS/hhnUp96NmUPm6yq6XOV6ICte
+f0hUVcuNnXwJitsPFpVJbNmECNE7EI3au1JOKXBBlfRet7IlXax5AgMBAAGjfzB9
+MB0GA1UdDgQWBBRzmA0meyNb9xdcsfCBrjVMIEyM7TAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVz
+dGVyOC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AGgndV+7vrrWgSHSMdpGymWF78PexgQBDcyUv+qM5OawYbreSUfOT9lcLef0TFef
+oX4wfin9jP6GmazZpeVIjAnkHN1OjVE/m+4VD+eXnS0pb6u66S7KoEJflliXh0Eq
+pY1axZraGEzSaL22ac13jimgrzwHuDP0MDl71S0e7x93/k2X82MrK5jt6mNw5Fz9
+PQHAeSBJwyFTRHDMW0L0RviIoUg/rskOvAMu1EzydVsktms0B2BJPLW/KGWp6u3S
+NvRctRml1QO9ZxfgxPJZoWM8NsQplu82xqvA1wOhZ+4fLD1lk3ylEwe5xIYVd5WZ
+oN3FzFHLoKVW5so8AyZQG9s=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c1.crt
new file mode 100644
index 00000000000..7d49edd4147
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c1.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUdTJuIxtwEbOb8dF6m54R36J4KrgwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0
+MTMyMjEzWjAQMQ4wDAYDVQQDEwVuNy5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAtut2Om5X3xl8drxF/Jf/qq+xPYYGs+soYtJM5qAwkC0NGQwPCIDw0pL8
+hpuJXT4WrtGmADZ0ERvPULGTMcBVzmDgt5KANUT8kt3NqzdDS9PXj3VAYKKuDZ6S
+dqqW7dEKhRmZ4NPERtHA12dYvBgHmMoiWOI+jvas2PvmJ0/dId8CAwEAAaN/MH0w
+HQYDVR0OBBYEFMcRlGJupnRk/6cjwiEb8f08SMxPMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0
+ZXIxLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+JhvxXe5MYkolRzbhyFiCZkh4STPxEobkgB2wPqvxd53/YOzfOdE7dmhyspdqj34r
+7j/JqZvWy3A2kjsoIefWV1WGNEjfNsApJAPa69+iCzIpLb5m3hHckDGtrk+JkQN9
+9UE+2GvFsJ1Y+mb8TGZOt7l9vzvZeH6waTV3cUifKFTO3dbEgERA3oGFjPqF+utJ
+HEKtOkId9jHnzkEOs1YD3vDndIfuVv1Esav8vXeXzDtx73AREfoVg1VEgF0TnVFZ
+lPC9kt5AIrjLYOx9Vl0EabpbmGgB0fV9cR167zOYPlYLp4s5mL8jamkbo8arx+2m
+/Ayu7j2j3mCnDM8hdJUoSg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c2.crt
new file mode 100644
index 00000000000..91d98d23d79
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c2.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIURYFhQEC5s1rDqkRC5KMkc6adOgkwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNy5jMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAimtML3GHPYlipJXpvuNCtUF4NL0qORN1iKA8wSeQEJb4a/zhPF5TqBd/
+Ixd0OYvUD2dsqGmQNiHvoUp13siT9++3sjFrdE0x7y92AwkKzl2iDsjN0i6dxIIa
+EYpVf3YVDONrcj0kbb+OPBG268pstENfluTbhuTI8RaJ3Sne2ycCAwEAAaN/MH0w
+HQYDVR0OBBYEFPaU9fqpl9MA7iS5rdP2JqcNeQI6MB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0
+ZXIyLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+cCkIr6yLbz7Soe0pKkZjK26vBXg/GSn6Pk9m8YRzAlVmMOOTwEjaEB0mPPDo/0K8
+TwTvxdgghla/wVbm6j8X7J3MpUYyYqjUOW0SqBM7THrenNEWMgFqFVo/9Kj51U6b
+kM0yRpxaOhL8QFKklldQpmdzLUlme7ZpodmOOYdNUcGOzqhsKptJ4vYc1YgzQgcQ
+fBAGpgS4tb0KFUWT3IbZYjj+NI6gz6xncX2KSRiglkvX2+IT/Vdo+8k+1s0VCs9b
+U1PL6ufye0ZPcl8uqEqrCLd6pJu1A+5FajnUqAGfRJIbzvslpSqyuFAkCAnFKpA+
+kGj9+HvreJYiuATpOqEV3A==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c3.crt
new file mode 100644
index 00000000000..3a04cd5cf84
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c3.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAM/neT1zlMH5MrdlYtC52vVP/WAQMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjcuYzMwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAIznxxhfyJLtn7A5vqmMhlRHfI8NXkNTxlaGhuXE1svx+B6PgkQeHZXZ
+Ium+ofQO0Vtam72SYLHXiwY+NrW5VNZzmJxd8uUjSHA4c8bO/UozcYzSB4HXI3lE
+eqSzLwwT5PtXVy4KBzHdPFJ/IWpyCvzQPGYD/I9o+e8UutoRRohxAgMBAAGjfzB9
+MB0GA1UdDgQWBBTj5a/lgJ5f8S8/AdEvVUD5dfl61zAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNy5jbHVz
+dGVyMy5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AKhwKCJguaevAFQ1cMHUrotPajE5Muu2CsIhXUR+j0YQPiax2wUdNmHvzjNTm/9g
+uTNsYa/+FFQom9LToLZXU27tGDjfPERPCN2v8rJVGWR6bCWujEMRpmjJOT73dth6
+qTdU5DY9Rn6v/QSakmBaAm2yF3UTNtd3NXM9PWZlDPq/dvF4Cpv77QMIIpwYCTO4
++GmYJ+r6RHqocGwPJf8ZXFoMuJpSxzbilkYVzRNWHRUR/c2Z5IsuflMXKdj1iKT0
+81FfQAissG0ied7anNO7QePQKcz9DR2SdtItF2ujMXp1dRezFNMbOQUW0v/iD6C6
+G5sL1K02vl70+3CpIk4Pfa0=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c4.crt
new file mode 100644
index 00000000000..ec17b1d016d
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c4.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAMPIOHRQfF2kDqKTYZFJL47S67T+MA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjcuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAIjxhvo7UMgEzsm2jc6fAwUSuKyruhbOGFUVWp3wgdSNxRPGEXYdLskE
+BMOADYMcGidTKFxzHl4XK40Qt7GlIB3nsSsttrJ9GChA01ngClYYNQvAaaV0WUxq
+eFMIUcRnYENaBS40J/jXE1KOEsRBKe2mphRWT6tdWLWLKdrGwIFbAgMBAAGjfzB9
+MB0GA1UdDgQWBBQyBHPb5d1Ym8c1rB/MH85v12IeBTAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNy5jbHVz
+dGVyNC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AAyj9Olk0h2NKZ5ayWC/srj9uZb0lcR67shQpgclJIvAsvjzitcQhjmL8intD32j
+UkPFrm/KGEuxitT9nX7gEKGQ0Qh/4c96Co8c4UDxd/RDWQnL3u/LLPTW7H+ZJh0S
+JH7pzT7/8omnrAh8OqqHl3961uLznvRNNIiu0ejpNRHwXFoPk9oL65U1syx8YYx/
+s48dbT1stzImO5TLXv+Bpc5gDJ7WzN+9G5E/f/DJ1etIsgS6r87roaq7WtEjFrvS
+9I3Ci2+nIL5U4q+6hzdilvMiyjTtw2fQKEVQlp5YdPArJYaIjqzggQOUhtBnCSWP
+87bX959dMVWMEJ6ji2zi+3I=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c5.crt
new file mode 100644
index 00000000000..f2e2cd8620c
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c5.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUIXgmPdXIhG5qFawuVil1bGWGKJgwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNy5jNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAjEj++bXevuo7QkfAhTmoUwf0WcA24+pQWcNrEzq6KtxprsjgvDEoynRJ
+JgkuHj5OGKEYE6Twah9oWPzRTBAwjSzfKrGfUlor4M++9K1Xk/HkJjJYc6TMt/pC
+GHVwY9GuxmutianrjY0BBab/y/hJXgGYDNa49SGN8z6TcWddsXUCAwEAAaN/MH0w
+HQYDVR0OBBYEFJfy5R84iMmkiqjDjTzeqVWDwWtdMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0
+ZXI1LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+kHXlE5bnKp87EkelJJZFeGsoRWXj60OrQ+AutCsY5k0iP6lbRSfwfaR5A82kxrSE
+e5RZnFKkX5BgIpzNy9zuQzI5O6Iyt7ipghF4EEwptjZOYO8fNHVRJZmX7fTzDQIf
+cGaXaiHTsJi3HP3H5xbnRI/3c+f+BlJsWY0qaH0OqO5HzJG++IakShu6q9cWCDA7
+tixV2vaOEkJ71IzQ0UGSTXp/3TvZK6gKtOWD2oNk2IUeF+UEo9yzEuFox8y3BToc
+EzsUbctLmubnVThHfvKdJI40lt8jRAKKmFxe+xxatEqPrGBVt3E7bvhKhvhwxxai
+mlPaR93bxokwBI9cbGUdzw==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c6.crt
new file mode 100644
index 00000000000..4df4def3107
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c6.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUS2riIiKq6tZ9TLvmAmtxF0HCSIQwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuNy5jNjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAi7y7aEYewkqr2jpU4pwCkxpIN/6uOvfwl/AI2APaimOrbSo5E8hyuWuC
+AnZt/ETmjeFvdt1MISlj2BbxfwhHDAB6qAH1o0t8h/n5GjGlrA1EskNAPxGao43K
+CsFiki3ulWQMsdGceqYmqdMYkwZs996dTEfOn6uu4rNKF03wA48CAwEAAaN/MH0w
+HQYDVR0OBBYEFDxU26jYM4oNL4Ey5G4IPGiFFIWyMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0
+ZXI2LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+n2m5XJSzf4OFXLVy2CeCMsxkxBCg6UYjRm1i8BmJ8XdSJrm8Ke0V2KRhe+0aBoy8
+rgVlQd5xD85GJNrvT0N7bA2tGSkDw/ucuzcqywzfgM3Sfzg6r+/cs5wSeFQTHTkP
+2CPWSqRJlD052MeLIVUXs6lG2nZeO4TQA9W0qP5T/Wn7tQXh8CdEy2C7Xs+uhUL/
+8eaR4OTSqV5EJCu3EPsV3YY6pZTlr5AzjWIUN+1GS+xg9dz4BatX9n8oB59PqxvN
+5+pgTekpJY6vsnyLbxb0WKDFM6EnHJ3hN8GIoI9Hgbak761X5KVo+DIIw6yq5Mfq
+FSJ/tFhB4tQ6sbSodVshgQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c7.crt
new file mode 100644
index 00000000000..38ad5dec9be
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c7.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUJTRrnhJztqw6LFCszsDD1c/yPR0wDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0
+MTMyMjE1WjAQMQ4wDAYDVQQDEwVuNy5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAoN6Ca8GpbkzxmORqC/sl3GucqCU/ha1ToDUuJxwzS6QTlJJ83DFbqyzP
+pIxx5YAhYiEfruoIVW4hF6L2KrQbKfAVWsfWHFqBpMycmy64yFCOK91EvHJ9Rs75
++KloOtSHgB5d4akgKOOBVyLHGeH3Dyl7nrUfi6FtCyfVCAjA8VkCAwEAAaN/MH0w
+HQYDVR0OBBYEFL4wJd/SFWld5TliWX3H9JPUcTD4MB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0
+ZXI3LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+gte0h+EhO4I0QoohsX1/q1IsTb/vKAGDaptx0LgXK7WkhOhyY9eJZZWp7JoZvhLw
+4eKqbjyYAxsATDxq46iAWy1dz7FL46A8+e42nO5a6DSm0suufkz7sFQFM6gBrjPT
+3zpD+DhH7vNm+lYNMzq/TpH2YoQlUrivrGS9PSWafmI2jZDVSBpcVbfJoaKUYPuc
+JRj2g2j7rEqWg5upfSCnxocQJXY6v8QI94ZtgbXwVmSZ4+TF1nJ28j1ogAKNjUjs
+ZvUWAbqqO0qzhtK1+X+w6wKNpZguyJ1tQRJ8L+hOJLbVMQIT3s5mNhQyf2qOxdFA
+pKlth68w2dZS2wGBAuob8g==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c8.crt
new file mode 100644
index 00000000000..63d393928ee
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n7.c8.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAPbvvAh3R1XWARmT+6y4h/F8+sqHMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkw
+NDEzMjIxNVowEDEOMAwGA1UEAxMFbjcuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAJEYBwUOXOWE0g3IFtEJu6bR7NCyKdZKgZqhW9CAUUjsJMppUfetDm1K
+RmNqn8cRGmjFkbGtxxJsf+cVR4q39aM4YdCxkMCOmagY8Ay1L6TBg/i65eGcxiDq
+tBrjKUJABe/4Fd99ehLugyXm2e/kRBQoYAQnlq9eI2K1lILJfl3hAgMBAAGjfzB9
+MB0GA1UdDgQWBBTUO6itQmiX4Bhq2pTA1j1OYwkVmTAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNy5jbHVz
+dGVyOC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AAgAeinlmvG7soZGQ8ai3gyEROpwIMpN3yBpgbVV9TKPAcb8Y6t+QRFHztuCFvWy
+N/mijTdB6nuhX4+pHA4pX5V8bL1bjmoaAznR371y6k3b8nRGinZEbAQbahMqefZN
+js6O4XFMJ3hloSmhJT/FnoaRNEZtsdJqdsTlZOS3fA3asxN+INgUaZ4UU6NqjPk3
+xQJD9JV1KFIEakQgWUGhm3RJ33Mb2rlMUZYng+p5vMviMKNsiFrGYJbALHWFhou+
+rR+iUylabeSK4UzswgYJxVwcnly8dsiJayn+7j/CDvwHb62hThcN+Ejlufk0v1Pb
+xmXE9ccZAVthc5SfF6Fjrsc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c1.crt
new file mode 100644
index 00000000000..f2d915e5cfb
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c1.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUE4wv8m8ca7CSrCJ0W242hYULIcswDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0
+MTMyMjEzWjAQMQ4wDAYDVQQDEwVuOC5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAgXuRBm6AhPl/n0w+6htbZqVgDzHBd9Cnp13KVWFj/aRR2v6ppf2/ZWSP
+DAp3zcZALQrPOnwlNcAlTdoFYbTNhdiciWb3+jMNSuwZaiNODykWoVUXeF+dHsWF
+mSjeQydkxPK8AfPwS9/8/wTvR2qjFPzIKYk/JPubG07c/BxC+QcCAwEAAaN/MH0w
+HQYDVR0OBBYEFMLuWtBmdv4emh//95cK1tzKVxLVMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0
+ZXIxLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+bdgDse0+Su/oHRZcyP4IaDBUz6L8qp3CFoJsztJN8ja5h19AJ+PXI0amhZ4clwa5
+qho2GqLSLPtButFx/9y28kSCpme1qgXK+2ySwUxOOJDbKCAwDQ6DLZ/umcyxFzxB
+fEdO4QL7lWMfI7hriyNHc5+ZjqqK2i7dP8zamTJ0zsAa6Y7L/jxvRIUd69O1skHv
+BXyeY2bY57flre4JCO3kEvhVtmQgpe6Iggl0hDq4SZ/3GlA9QoLz2ajpCxvQtyzN
+xWuoYf5ZT22yVdIG7Nrpe+eLUjhT1xHQXv1bfpyNwfGlr8OOs0jcdKvENC9GqhS9
+BchqHw44qkBP+5rBljxhAw==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c2.crt
new file mode 100644
index 00000000000..9a6cadda096
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c2.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUePVFoDIs9eiIrAMKc06YoRk7oIkwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0
+MTMyMjE0WjAQMQ4wDAYDVQQDEwVuOC5jMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAtfvCH7wJN5iSoyeWtfeJFIs3BrCtS/cb4LI41nam3g9T0Ag9WPhf1aPP
+5QBgDQ1umY0kuZEhojduZHgZVoG7mNVNTgqSJCJKooKR+SrQ4gqaIlgIwSpKwo4u
+/za04p1OqRhOJajOMCuC4zEz9yPt1YAfXCkYryBlne5m7Y+mVncCAwEAAaN/MH0w
+HQYDVR0OBBYEFLpfZ8SVBLNw/xipDeUe27M9REyEMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0
+ZXIyLmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+dc4bAOe9GrWL3GWSbNyvJJTxEMtlAXTrAlP2kBW2TpiGBTXZ5X8+E48NHAn7SsIX
+W2DvqglKam+ooe98XoRwX0UPTikPNaC2Ud9Snxs4OqpQAxE7XPUYV94FsyRXFA8M
+fEr8REStbQcpFLlUXrIAZjmGlRi6DufLxoGqgmnGS7KBEt3JwEvh7DHkSka8YMx6
+Kd8YrtTPf6ZJuUk/gcmZ5oK/ImZK43asW3b7obgS/wRrzV5OVqx7bvSBd9pfOXbe
+TXwxWpciRGOEHoanIqOWSH2xoWnuzCsL1jsku6d6aX7i2HyddeC9Ler9YOJyLlaN
+tjym0gGIwk4PRCcZ2RJD6Q==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c3.crt
new file mode 100644
index 00000000000..8b94517e3ae
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c3.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVANUiRixRh0fDx5Rw/fcEb1n1Sg0cMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjguYzMwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBALo0zeVKn2186RU4y35d1zlrEBBw/neVSSJME3AOj8VC/QgiQmqYMpWy
+UPp83aXzmlD2ZEle+aS8X7opg89GPCrZVcxK8tM4U4HTEqLP2VXUAp/I+/Vtv9fR
+1QQDB0XfkQx+qDUdwTzS4lv4cnFzsmVDgVLR0NzjD+3fu3bKhjDZAgMBAAGjfzB9
+MB0GA1UdDgQWBBRaBpO1OJaW85kYzyBLyLGRaE2HezAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlOC5jbHVz
+dGVyMy5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AE88FTjwLDZ8bsEI/tQtTfg9G7iSTlQZsKmIF+nRQXUU6b8EMtMDar53ug/yzzZJ
+fZshpjfUmp0w+pQVBt/xrrWLtaXqe+rS9rNzsByGbmTvkl4t36nBv0GOxtoqSdvA
+Cp7QcxVBvJkOK7z63oyxAhq+A1rnoxeUGoEyjuOjeIoLT+oTPLUSSqSmMwqxSIOx
+Q948cGwSiA9QtA8FcgC1TLcHFgTT83A0dBkYTPjJ+7gQwHEGL3kucZVQBBLBpju9
+lFleod93BW+Mdw34Gnc6WAqBEyNYIiOMkkkDXzgDdDMZazgVsPxiOej/7FcS4thD
+ibJVseFjLtnYOLPbv0Wwk50=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c4.crt
new file mode 100644
index 00000000000..1cd6fc2f321
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c4.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVANfDmHfIieWZe2vAwvx+WCiN/UuUMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjguYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAIhWp/YCB3cVIrTK0QP6LC5zBZ8avn9isi/QeLXwxw69k+qhHEOReoyb
+nPgXyr2wyXLuL6PwyBMfjINDIEZ+N+4TsbYMsE8HiPNYQyZm1mpBI7ux2FbgCbpu
+JRfKA/Pztz4arlBXcHG/tJKistvF+SSrw21t2bLtVZHXBFR0c0NzAgMBAAGjfzB9
+MB0GA1UdDgQWBBSapaWx6oupzaeRg6DMkAo0HwOYrjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlOC5jbHVz
+dGVyNC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AGkVwo1x2FNSMDj6bUxzyCN/MvAIKSe4oRXBlv1ZAWZjG+DRmJk+QpPmkxgtooue
+6TKRTYARolTc+gJtG1MqyWoJ3QSekLvVg2OAKk4qq+ijIL7zHaKTECPlzjJppddG
++/OoCh8HDLnOcbC9UU36+3M6cJARFTv0mJZob0kaG5mo67eJYnknJzz8Cvq3r0bg
+xk4CE0LR9+evM/wMz/M9m+jB7HdgRcLoTU2xh0v6coVnJPYa00JL5YfRJuy6MCJs
+LHveTDYh7HMdxXwnHhr5FkdW06e08OJzzNEc10nTC+zCpgaGCTJxFM0mZHRskqMH
+QoDJUQE0/8szz0KfXFb2Vqc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c5.crt
new file mode 100644
index 00000000000..b80546ca1ca
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c5.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAPqm3dwF6v7a1hqPfWXePuwO/oYGMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjguYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAJHAR+FS1lWCkwSuqgxJOTy58WVcjIkF2R0mCs2jmCTjcptZV2JL6VyA
+3G88MjchazG5Ebtjl+4CbwyfUV3GR15sCTFq2EiGM9sCzuemScmnv+dR4u2P9zr9
+EKSK/CcNBFbf9VGT4WTt5ebYj6eIVjzxSTt7OuIFCz036nL975DxAgMBAAGjfzB9
+MB0GA1UdDgQWBBQrezQ7l6dt6YqmK7niD66JMi+bqjAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlOC5jbHVz
+dGVyNS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AFEcqSWmXLaIGLekW9XTyVwTAbU7be8A271Rp8IIfWFNrnIEXz/Cp6JChCpvCRxa
+GjHaDFimp+VRGkWm62Ha1Acbbf+ln8YHFKnaq2adRCZW2pF5wuNMqtHlMS8B+2W3
+ZZ9fMXrd7kXxlzWpHGH/mBLASfMIac+wjgctbZZS0cJx6VbZmH+XSNlqJ3C2tSYa
+7CaJHZUVClXL/A5m4u2LyDwqMQfixfon4/9U/NIwbO/pUWZ/wdqq1BA56Hd5DjVr
+C4S5MFB6N7jETb6NtHOHtezewOxAofSMIv4e2N42r7ydGI0OKEu79LEVe8pyXqlP
+W0zPUJ5D9UaWxdAo81onXzI=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c6.crt
new file mode 100644
index 00000000000..361a392effa
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c6.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAZWgAwIBAgIVAKbC2vR+wY4bWUJqzy62moQV3NghMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkw
+NDEzMjIxNFowEDEOMAwGA1UEAxMFbjguYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAKPAUxo+4TTrLmVCZ1WoriuC80jKaYeDelj1F1AvT7eajep1MiDoQgjK
+Wl56n2JeJiTPU49Dbw8IdgK+Sqezv1CErVx8VTsb/ljquF0yzWTzjoMPKa/YtgQ8
+KfdrBMcna50VF/7uIVvvxbLIsN1qQQhog29CSXqwyw4RjAVRCVvLAgMBAAGjfzB9
+MB0GA1UdDgQWBBQ8LqFuicvzgfROGbcN315QOD464zAfBgNVHSMEGDAWgBSrRunq
+ZcqAopdSp1f7svo6+5eoXzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlOC5jbHVz
+dGVyNi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEB
+AH8G0DRTzIWEbC9VZmnVxT6L9LHsc6z+9y8evNN5gRMAFMxfjaiTRjibqwM8+hjz
++oaSmBzkzY0t4WcljtEgvkzvIXEEVVeY/MBdppXOKbAh1wMxPDzD2SCUu+ILITIe
+uCALZM8NucxqoOQeFaBXrtrn2y4mTzXVfoip3FZw1dP+M6sAEwfFdRBo051r5bzn
+ZEC2LgpT5eOPWwFaMTj4I/qq6Ce96e/+PoY5ivqo16STPcurYVHd4yEr30lyDEPq
+cc1jYEUNpVuklY735gfdPi9ec9y3ioLUCI025wLWlr0PKOTLhUOflkuZnC3hM6Jp
+R2Ebzpapg4YR64kp6W8X7lo=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c7.crt
new file mode 100644
index 00000000000..7cfb81868cc
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c7.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUTU/oQlfBcPG83Lt2OtobAowVER8wDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0
+MTMyMjE1WjAQMQ4wDAYDVQQDEwVuOC5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAuA+oN7YU2z47w0L21xSoUQc1p7LlrHTbYZDmoCLKQqg0IUP5gvENBbzE
+0+rb+ckhpCHPKZSL/Up0+zXiAPDodeZJRc72O4u/jXc9DcHhpV+w4obT0mZQDEtt
+ygBDY+t0WJyFZZpgS250XhHMA60w0ZuP6fhAvsmQQDGDRmX702UCAwEAAaN/MH0w
+HQYDVR0OBBYEFHaUc5wM5Ve1XrEx3aYe73WSwSWeMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0
+ZXI3LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+WSFyo3bRteiJe+iOL07z/2PTuB6LfM6klZTllhGZuKDuXM8teKluOoJ/AgkVEb6/
+uuqzkAHncMVy+BiYqmweR7KKT2siQgyHMl/tSMysn5I2YVL/sneIsdreGZkAUQCI
+bGCCPuWbCX8OJAayVDS0U0zSfwsAJoBiAjUDK6ZwzVdimX9WTCJcx/3eJgrdPese
+Hv3XoeTWocfWQeA3qSRb6YE6yOhuDvPgM4H2jsCe2gYeOYeNnD1BlP92T7epaxx7
+00kMsZgY30VRZ6EQ7Hkzghc/9VXLd1jFZ/ICC9KJ2mSjCl0in/5JJ5+uCSBybbII
+uBwjvpppSFUVLimeeIwCEw==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c8.crt
new file mode 100644
index 00000000000..b85a2bc8ff3
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca-signed/n8.c8.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrDCCAZSgAwIBAgIUX5JaUQz9mUV4BlmMMbsDzYG8Z9UwDQYJKoZIhvcNAQEL
+BQAwEzERMA8GA1UEAwwIY2VydEF1dGgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0
+MTMyMjE1WjAQMQ4wDAYDVQQDEwVuOC5jODCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAwvRhMUXpnmopSSajgAAcImV5vnRLUB88duRl/j6oM0Oq4xxPoKg1HfSj
+TnJuLd3mrMuTQPU67KodJoZ1keFoeKQGH1S6pDT+GBI+8IcZMZRJXyeourDB5Akl
+qRVKPiciepoVCHuePYZKVlsUnWbH1Vg9yMcYW6Jx6zbnS/meIC0CAwEAAaN/MH0w
+HQYDVR0OBBYEFO5ttLIFOaMQELSrMcKok9nD4PqyMB8GA1UdIwQYMBaAFKtG6epl
+yoCil1KnV/uy+jr7l6hfMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0
+ZXI4LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
+g2NQZrSAadjMDCpeTeSTUJFP9SL81fOJuxK8X3VCTZUtFJAUJTKgrjAZWkDXWcYf
+47lzAoHuCI07/AVGkjWepQTzW5LdZWOdc9osIKRCnb9dofIrWrMYoa+1BVOXvasM
+aErtrlFze3z6WAznQPjQ+R/phpwZSJksAGJ9VPG7AFla0k2oCjOvu8FJUHev+ft0
+9D/ze7TXrIKOdev75iO+F+xUZJnUzDk+rJeWQYC2onyHMUA/oskpkT9GqV4eIb3d
+sJkJVbBH0V9iMahX+9FeYf12colMBUgK0lactFMTrqzP+v3v3vY39UBlDhR3x5JJ
+3pPRrvAcnxZ6pobwgNS6HA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca.crt
new file mode 100644
index 00000000000..81cd2ca9239
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAeGgAwIBAgIJAPNwDUEOpXcaMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNV
+BAMMCGNlcnRBdXRoMB4XDTE4MDQxOTEwMzMzOFoXDTQ1MDkwNDEwMzMzOFowEzER
+MA8GA1UEAwwIY2VydEF1dGgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCvp5DCd5QQtFFmSJQ71R0iJy/Ho5mOkSGaux2/ZAaWVXp4iv5cgc/mH+1Co/PY
+GLPxc1ZIqv9FMxVCaNh4Sdm0R4sVqw7x7rKXfJBtM31CSek87FUBPZp/CTcrKaQR
+OOoDPDGS7UG9YK4UHRXskLQG/aAP3xf/11baRhA0sbx+a8ra6p5Qj9ptUHwqmRQ3
+cpyednMU5WqJjrtqsY3O098elvXPSLvtd/dHVAiDAZuGlpDz7l6uoiifnWC6NqYf
+ZzqtEom4En/PM8p1cLVptR0BNSWuTR5bM469xVrLMowjJZZE4/j5WPfrF/3H9jZl
+Z9WK2EQBUOenX2YPvp60MgrtAgMBAAGjUDBOMB0GA1UdDgQWBBSrRunqZcqAopdS
+p1f7svo6+5eoXzAfBgNVHSMEGDAWgBSrRunqZcqAopdSp1f7svo6+5eoXzAMBgNV
+HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBr5e/2NmsghTfN+jS82Eovd/TI
+Ur4pjrpgyU7xgjqQcQFXHeNIyvf65UjHenZ6C6JPffBWjH+wxyk1CgyXdcadJ2jA
+Aeni7iaSgSlzxoBd47sxqrcHMsohXv7RIbJgWV4oQHMGmJ8PHzQGyvkDCXm8Q3qk
+GMSGTg6APQKL7+ixkAHs2c3s73c/vlhaTLnlUOUeLwJc2q6DyHvhzLyv/0D1nrtf
+Md9xjJL1n7YUte4QDFQ4C0J+XnseyKkxcHuy4iJ3z4UhqIF9dgW1dBsGw8ZmH9zv
+4P+3gWksm/KPAJ4zm9tfs0Q1eA92RvggGlqcc391f9Tm53dQomsbiX3xLCzc
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca.key b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca.key
new file mode 100644
index 00000000000..eba352e1759
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCvp5DCd5QQtFFm
+SJQ71R0iJy/Ho5mOkSGaux2/ZAaWVXp4iv5cgc/mH+1Co/PYGLPxc1ZIqv9FMxVC
+aNh4Sdm0R4sVqw7x7rKXfJBtM31CSek87FUBPZp/CTcrKaQROOoDPDGS7UG9YK4U
+HRXskLQG/aAP3xf/11baRhA0sbx+a8ra6p5Qj9ptUHwqmRQ3cpyednMU5WqJjrtq
+sY3O098elvXPSLvtd/dHVAiDAZuGlpDz7l6uoiifnWC6NqYfZzqtEom4En/PM8p1
+cLVptR0BNSWuTR5bM469xVrLMowjJZZE4/j5WPfrF/3H9jZlZ9WK2EQBUOenX2YP
+vp60MgrtAgMBAAECggEBAK9G0dh7YjBY/nDGM8SQoAWYfMEFqxDsGVBBLynwMfKJ
+UTA/4hmFH2NOsH4zA/u6irSAlrTkjN0MYEZoQLmnV6nhShRRIRShT2yCS8vr+S3Q
+ewDkAt6+DhB9raNQZfsZg8m+oukt/s9uTcacT2hD7KCdLL8pqtUMmAoup7UtNh4e
+4a5l5tuDvCemxQnjMzljegcmPoOiqrvvi2s/FDz88LJuDB23v2gTjp5aQfVjCIqT
+oKCPJBrB6HyyhjNXjWZl2yiZ8FENTDWQbWcDN4niqrGMnnKG6xR2/ZEGdcVyFfME
+UzMC5Bb782AscYrJYnW8F0CGmFqoEbmtFMyhR7vL6DECgYEA4lYqLXKUExYvCc7F
+D0wkUwgu9LskUi5mULEGMeCZl98845VwKS17LqKVuLzGGg9KVjF4xBPSOLNFdNn7
+RRnaFAf6SQkC5xSRKL8+71Px2YzNbM6KqU04MPT2dN28mV9WjlKRYkOJf+Z2Kgnt
+v9GZGMMfEi90htwSnX8WGk3qZKsCgYEAxqz22V23ChQ98UCQ3xYG8yhjH8wqe57X
+Ju3NXwvdTrgRV+gwDXdGDgTF86Qz52FsGPvNMdefLgOxrhCQDpaFLLn2kVgueFoR
+LzQiBuweSKcIGJT0LqQXYxOv0iK7OUFBXEEXk1YXFNJCdd930jrPhDgs2C+XNpZ5
+FlF34XAVXscCgYEAqsWofTH+V4hdZWEFfk1M+vkptK2e8gLgX/GxYuC8AsMFBhIy
+1l7imoVBwmlsby0qQW6CWC88ZludBFWUKMcgrAx447JQ5lm2TLA/pAQKbsK2HGqa
+ZLNGummZqwPC0VYF0MyrtSCQFlikv4NOR3S1tuFCCE6V9UsHIJ5K5v3y5JECgYEA
+l2fI1u3sR+oVKn2h6eDHexcUM29MENmD7U7ca8qG5S6xSOTRefGjmZtZn8tLItHD
+p2Z9gbZowJBgH97Pac6bvvIZTbp974nz/p0kMVJP4d4o9VLOo5y5le+y1dlSBNgO
+D1grt0SsYlm5/EpI7hWTf5ev1TCvdBJIRRHg4hSgtJECgYAGr8/xTDQsCW0TCTxM
+3wG1ivwhHakNsnjkDMhityauJK3S5JYk3zC6PtA/iUy7Bu2ofs9p81ZJDnF83Yhw
+ijV7Mde983dIwQJXGpt/42vUdx5CdN1gybGdZfQQAVKIsTsJHT2D28C21q/Yl69U
+jk/GnqHNoXkMiMrzX1Iprw3KIw==
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c1.crt
new file mode 100644
index 00000000000..bca151e28b1
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c1.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVALishM0WVKx4AixPiFxwW8AT9G75MA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4xLmMxMB4XDTE4MDQxOTEzMjIxM1oXDTQ1MDkwNDEz
+MjIxM1owEDEOMAwGA1UEAxMFbjEuYzEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAM/q6yVK17PHtdsO5pM6DNU6pnOY/FQO+c1JpD2cpOk6B8yokEtFR+a0Qsds
+qQewAGBG77u9jQVerJr6fkPW+AeJT7eEBl5rqYDx82XgeJS6dAJRvclrxsOLBDDW
+sImDIMes0AZaE54P6LDGBooH3XhidTyFj2Gp9fozVY8PWFl5AgMBAAGjfzB9MB0G
+A1UdDgQWBBRLyFFKNa/ll8mohWv8TJyzCzyOmjAfBgNVHSMEGDAWgBRLyFFKNa/l
+l8mohWv8TJyzCzyOmjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVzdGVy
+MS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAv/Gm
+maKqfIIGPLWfRv4/GQRssogAOHdqlZcYojxQ6Ovo6ped9qxscYXGb7+8sP7vIeR+
+ibXEoFvbObfM4EyRONo414PTyZnpsg/Jqe3GAwnd4UNrXR1LLcFyxaUDoDvAtKkh
+nI0iE+0yGwrH8UpMuLXyqqp/ivTlTkMBdFVvenA=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c2.crt
new file mode 100644
index 00000000000..848b7c5ef18
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c2.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAK+lmh0imRaWbjXWB5mEQMqEUG5pMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4xLmMyMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjEuYzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJQtUzqzNCr2cWeNAQnn9hwkDhrBSPyFJhQlZ6Otkavw2Z0G6arPXsgYw3Sf
+ZTBE+Gq5KidVb4NK6HWVgoPEzlN/lq9cVdbtr+KAU3cMn6DK2cSltzbTBkEXa7Lk
+5H0Jt9qLquHifF3H+s4gsAKbqCCgz0WYqbvvSapssKsOOWtZAgMBAAGjfzB9MB0G
+A1UdDgQWBBRuBoJoTcJq4QacLWQDLb927B9j6zAfBgNVHSMEGDAWgBRuBoJoTcJq
+4QacLWQDLb927B9j6zAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVzdGVy
+Mi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAVjwG
+V7GyCbpBNfXgjVNeO8EygBUjND27dO15a2ElwcNAG7mi+4f4ewIVlf06kzXLzFu7
+ig2rV8YiCDua3FctIWDhrWrvvk/xwoTw+o8z3RBE/4q8m/60BWQATHdmdq8jBBxw
+oFhMS1yKN5mnGdEkfPuq0t+wK29BPU6jVUsHJyg=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c3.crt
new file mode 100644
index 00000000000..b655bf344d8
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c3.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAIxnFnx8Ow1xmNEHSzoEFNU/as1+MA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4xLmMzMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjEuYzMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIVyhLjNcWHszffIzSX7aQRkgEOIzNFuJ6z/OjYX5SoQgjZ6ej0oeudbeOPr
+/LT6NmcIWgQJHIa3w7Rygbk//+jyLXshG7bI/3o9js7UPVzuoePt2y+nHFYHzL5u
+mA9cuk40zPXwr6W7aqwTKLhDmJDzywOpcdtycluZidy8MJ6NAgMBAAGjfzB9MB0G
+A1UdDgQWBBShH89k+Y8GKljoG52TiS9pi5KrQDAfBgNVHSMEGDAWgBShH89k+Y8G
+KljoG52TiS9pi5KrQDAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVzdGVy
+My5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAb/80
+ShzdMSxzpLi3kQeOyisoFclkGcfdZAk+wluPJaZjXzu6KdaUV6J23pC5NJ1QP6+N
+2xStsISJt+Cf08S9Oxae4NCAD7mw18oxQveJNlzX6UF+/IilLOGYI1Xfc44BImfJ
+bRInBM8Yip1D3tWqZcPGS/wSlMq2IdyVm1tOPpI=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c4.crt
new file mode 100644
index 00000000000..3b7b3bdbf72
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c4.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAMllmXfU0dH+YEE+7NFAwve6CVRiMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4xLmM0MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjEuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJVhOQxK4DAxYsFDcm42dl0DdpRCqxYFecP9QmC2cniv+sMUSRLsti8BeOKa
+wlWL+NQK7CJhAQPuYnLEBiyhUIFz9dAVozHyOqBKFbf2L3A2nIPuom22UiJN79k2
+YXZgagSCdCdRX8WTvTRbbN8WYRfE/wLO4SBxwW2f501ET6pTAgMBAAGjfzB9MB0G
+A1UdDgQWBBQIGCed24kXamJPxK4inO7BWteawjAfBgNVHSMEGDAWgBQIGCed24kX
+amJPxK4inO7BWteawjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVzdGVy
+NC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAMNvY
+Z5SwaZ484mzdmNvseZs8cxZA7EXeuOw5r9jRyeeYAT8aJFBBXgAYx4h8in9JbBnP
+of/88YKTHuVYGmh9ad0wP7TruZQWF+siQZht2grar9sWo8XBO3FiUBHsEfCvSQKv
+ppkkIu7YiXoBdpdpx+6+lYW14L+fgB7BrtRODHo=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c5.crt
new file mode 100644
index 00000000000..eb405cef94c
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c5.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAPqYnJv7Ib8hs7fwymtTbafjPHznMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4xLmM1MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjEuYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBALGUvDdOnTe62apHl5sXV6Ys8GYqKDJ0e1cCQCKgxu3MyCueXC1xdhYJceA3
+PTmnTRg7KqYhJLZi1sujBOfuy7vsg5r/7L6EhWDCM/d2QfF9ZUft5ljsEGYNOmGa
+kQnU+mFOuDe18hlp72tavC2tdPYHaTmd0t2f4J9ovxQznO+jAgMBAAGjfzB9MB0G
+A1UdDgQWBBTgPsBAr0vFIhwmOhBkC1XvlAGtvjAfBgNVHSMEGDAWgBTgPsBAr0vF
+IhwmOhBkC1XvlAGtvjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVzdGVy
+NS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAFbiX
+wn34AQsvyD0AQkMy0G6ZXH0UngtGfW6qyz0rFNNRtV7VnxYjZvuXKiZ4ixaHA+yv
+heUYsReWoWzZAb4SYyxp4t5fuKxIF+diW+WelUV9FvTjD/Ynzp4jnxI2B1+2InNd
+WFcODD+1pYaOoUoM4554Ir84GoybcvL2iWAJX84=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c6.crt
new file mode 100644
index 00000000000..cebc88f9979
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c6.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAPQ03RwYzZEGZE9BmLB3yibXdFlrMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4xLmM2MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjEuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJGKOOMmMfmt+9VRZfYsorzOWLxWRtqD9VjRimbBVWBoIFYf+EVyEC0E/sg8
+G9eWAcSEUJ2oDp5dnMuXzEZrA3aaYeDZjtOYuHF+i+PFQQFlpY9A+NapdhJe9CU6
+cvL4ImRyatPxw4A6QLLetWHbDDIYA+6iYtmkKTkMlY6bboSzAgMBAAGjfzB9MB0G
+A1UdDgQWBBRs7k4fmkFw8RmVU1f+p9SY5qNwnDAfBgNVHSMEGDAWgBRs7k4fmkFw
+8RmVU1f+p9SY5qNwnDAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVzdGVy
+Ni5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAEXhO
+vittRGJEOl5Yt9pEmw1UJ/TRum2osbMj+3+7QGlCpU+GC6ziMXbwkPI+AksCySBX
+mXZlgMK3j9oESC8K5CiWA8IpY2HcUJnKRFac6NIqYdbStVNAKJBMDvmyhORW2ejU
+K2MBzTHUyJtCjFmIlFW0YzWFgMUJ1fqHWBwpOZ4=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c7.crt
new file mode 100644
index 00000000000..08c2d4e7af7
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c7.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUccM78mwTgQTTvYEwDeDeYmTLBRkwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjEuYzcwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuMS5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEA0dKhFm8ywJ2tBETCUsdHzEVE+uVb+oLVVxswOTBJ28U6s+H/KSk+f4iQqtND
++Q4EI6u49KHvH3/koHgRuQwmcij5dCUuAtsBR4wZJLXUgqlBNLtLqejLF17vFTRn
+i78xiTQ9L5CBioNTYTGhjxQ3tUbFCD3NLPLd25uVNR9Vc9sCAwEAAaN/MH0wHQYD
+VR0OBBYEFPGksbL4MBmo+fWjS5FugVp5PQPyMB8GA1UdIwQYMBaAFPGksbL4MBmo
++fWjS5FugVp5PQPyMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUxLmNsdXN0ZXI3
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBfWuwf
+la/PtbA9kFYzzHozSWubOKUoSTzT4yyWYMrONU6rDll/x+nRUujrko3ecGcQHvns
+qvfLRxifj+TS0SQmGn2edgkfhNBke/rYfGA3CzuTmlqOiGdIz3onNEf/W97mfNu0
+ssOitDOTm3FipxkxvPlvfIOBuA4vUUX4MlfPaA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c8.crt
new file mode 100644
index 00000000000..feba2f614aa
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n1.c8.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAMUWjLPS533+7BzHoMpXAZQIJc6xMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4xLmM4MB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkwNDEz
+MjIxNVowEDEOMAwGA1UEAxMFbjEuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBANBMTFKHFmdHOxdIKRfUV8NVKIJe/T8QSiHNiXe2HA1TQ1qp8jFjXLnnoeWw
+aDNUqz7dKtjw5Xf66QXjqAamakTHzbtbdifoo+276v3of+9ddYYjjm6n3lnvK7zi
+nLjLj9l8kjuEp0rTgqUU26VicJVs76dlHsA0OxShdbbdAWJ7AgMBAAGjfzB9MB0G
+A1UdDgQWBBTGQzXKW5ORg+cp8KQkDmOlQzOIEjAfBgNVHSMEGDAWgBTGQzXKW5OR
+g+cp8KQkDmOlQzOIEjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMS5jbHVzdGVy
+OC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAmbRL
+wgD19qMd5bFbK1sYiasX4DAN04U2Bx21FRbuOXA03vGT+FVnVLnbkJumtIqBCGCZ
+sebCxLEhE/fmSX12hKQnqFR/1EMKvI5bps2996M6NeMTmdGCfJECBIuMN22DHIcc
+5Ek5UCEQJM/L7tQpdWBRl3q9ca4x8HeHLlDYSvc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c1.crt
new file mode 100644
index 00000000000..be43ffd28eb
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c1.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUGY+OrC0XCiA+1oCJX+CHvv7UH9QwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjIuYzEwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0MTMy
+MjEzWjAQMQ4wDAYDVQQDEwVuMi5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAm8aLIeL8o3DodD9VWa0KvotRwSUtWX+qzAFgM5SqHHymlDnwRJq6gutqnCDC
+os6TGihA6bnlVw4eRnjq8usw7cyJW2iIIFPr4d36DN2Ui/NGdICP4RMClrgf5sC+
+GE1jln0W7Jj3f76jB6HE3BbU6PCHdlAtgVcQ4j59y9dchI8CAwEAAaN/MH0wHQYD
+VR0OBBYEFOMdmsBGJx8YHfiziaJxU93Fc6C5MB8GA1UdIwQYMBaAFOMdmsBGJx8Y
+HfiziaJxU93Fc6C5MDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUyLmNsdXN0ZXIx
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBqgc5U
+S4wYk1VmWTI+8ezAgtlnsiILn70rfsi0KjI1hzo8PvTWLIVvV7NBefMr34ugqstL
+5by7pBAmKVf8Ut8148Jpbd48qxOLdwQVZ/Cthho+5u8i/eFmAJbATHkmyEj4Pfp2
+u9/QIikh8Gcm5sWf4CyC/7tDISxVHm1FsM3nNA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c2.crt
new file mode 100644
index 00000000000..f77708c2662
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c2.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAI/exdUNVY6z8nhKNGOdfOBbf0KFMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4yLmMyMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjIuYzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAMA9aZW2sNBxgc19xYUSmSG8/kZ3DHYcB02RS63y20ZvNwBIbzMoawQwD9Z8
+gfqf9zJ7JPnmkyvhaPygY3WpGzC30vxMG/XG6/pPWW0yxlyL1C60ann1r4BTdRbv
+ms4zaw6h0v6oePN9/oZ6sgjNExBBsZEV9UyL63W0LEcPI+9TAgMBAAGjfzB9MB0G
+A1UdDgQWBBS8HSfCvdf16vHBBjmbzPf+BtYLzzAfBgNVHSMEGDAWgBS8HSfCvdf1
+6vHBBjmbzPf+BtYLzzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVzdGVy
+Mi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAIAYW
+v7RbhTCsN6uXSIR94OHlbQCejHT2WBaJNecKNRXc1aQb3qUDiNkjp5TX/bokHhlb
+9lXlWP0CtX/w93PLgwQ/YG4HP+y18kPGvbm6s4E5hM5eLVPOj2LBewmOTYyJQivd
+6XLTaFmQnsMx/X/YMZhhVvymzM2HV7117aAR4Dc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c3.crt
new file mode 100644
index 00000000000..9ab1ccdd5a8
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c3.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAI32UnAStCMbefX4MfICKcGW3TPkMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4yLmMzMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjIuYzMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKllF4c9YFeQZzEuE/YKlcqHfDiS+tqENJ0dFj3cr9Mjg5Ju3JjHL7llZNrD
+7chh79YMinBbXi7AR/9Uz1dcyRpP3nKwiZZsn8oZyWCrmoX9EjeFPRBprWq+qOY2
+uUVVohJgGzZ6SUDxlawTyyOc5oU/wuYb4nmNrBsGT9tntHO5AgMBAAGjfzB9MB0G
+A1UdDgQWBBSMdkINXUsaLlfrfH9RuxuKsODn8TAfBgNVHSMEGDAWgBSMdkINXUsa
+LlfrfH9RuxuKsODn8TAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVzdGVy
+My5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAOy2M
+3ILUvZgwjWCpWc9q/2A2wy4ahFm++rjs9JzKVi+mSGlk60YEOFdJao/UxhFX8+qo
+LNZQxFUStfQDmyiWM48Fa0JZyMKOSiRGdBbreSaHaDI3lpBhetrOCf+d2UsUFfMs
+SW23cfeIDQwGD39xPjNRl+zPr36C5T5+1l1gBwA=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c4.crt
new file mode 100644
index 00000000000..8e111943b69
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c4.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVANl52f14Y2XwcvVk/EWwSt6iKbJCMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4yLmM0MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjIuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKMaYHZ4RiQN/cACOxN9GEyNtxwXC1PD5rD1nPCH0Efyg5SLcDzbBj5YVS+B
+Gl5HIQ3hwX62vnI9pRM8GJOZXX4UGHQ4gdd3B+qbW3n9K29cSqnxulIZiE+Ax6LO
+XwwEzSag1nTEpJQo09LZPusyzXnicEJ/RpC0krAa9g6gnvNRAgMBAAGjfzB9MB0G
+A1UdDgQWBBRsXxUJ6YradZoLR5+cQBXgj69aOzAfBgNVHSMEGDAWgBRsXxUJ6Yra
+dZoLR5+cQBXgj69aOzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVzdGVy
+NC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAlOSo
+5cafQgnZyRFGdBdyovfVfJ88JzH4G1YC0As+6cnZmafZ/pIdUiaZOuDxg9AI11BL
+LWlaX3c68kk3PWpL/vtJJg00QNhxzyHaiLdLbWuPoIcE7fDHvwbuOsXWQv446MKr
+Q6mIe90sGfGCIcyBXXzP8mOTAyTcacHTS/ZL3Y8=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c5.crt
new file mode 100644
index 00000000000..31d960f5e03
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c5.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAI/+n5L43cIAcNrDP3rvwdoNitatMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4yLmM1MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjIuYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBANLAWJxq07CPGG6VYspUbzyEMn6pBE0z9Or69wrDOKM7CVM8CzrN7aw8zYDL
+uOZy4cEJxLJKvtw5wQfh/JELcMH2WNLIFNABl5+m+FpNLBGgFMC48NUCfPexD7JU
+PAc7oiaZQ/CFCP+5YK+a5F7M9/SwVfQKKnsMPK3v6zyZkFO7AgMBAAGjfzB9MB0G
+A1UdDgQWBBTKJgGOBVnP8ZNUNlZXD0iNkRRDEDAfBgNVHSMEGDAWgBTKJgGOBVnP
+8ZNUNlZXD0iNkRRDEDAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVzdGVy
+NS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAbcaY
+9U5E3lyLp1n1UT9ejqHbJwQD+lfTFx9OPou9HifYG9qbNTg92lo3zl2lcm/pD421
+zvqQxz/Eyr18WE0qzzlX7aHuzpy7S9UUB8GnrbZ+oVHWiVJstZlTAOXO+gbPi1gx
+UhiXctx+YQO4V07f7pFFLkzeOT94Aaq6yLDqc4Y=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c6.crt
new file mode 100644
index 00000000000..e8ffcdd543f
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c6.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVALQXuI2M4/7RVxeg9uI+ABZLvK7UMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4yLmM2MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjIuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAICwXz/hU7DraQWX8TJWd8hva4KzTKOpq8JjnbCd1n3ovAqbDP6GkgVAJxY0
+eMFwP+u4jN2JZuTISWIUOmLGosyHpXsXQwbsvDLUC0JPb6v0/omkLFsrIXgBt2xI
+y7Bt3eifKUmUGO3ePi+LbgKYq7YNy1uVaFiYLR3PRul+TCXpAgMBAAGjfzB9MB0G
+A1UdDgQWBBR8+r3Wp4Dc7QfmCXkTGgz3gyfP0zAfBgNVHSMEGDAWgBR8+r3Wp4Dc
+7QfmCXkTGgz3gyfP0zAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVzdGVy
+Ni5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAc3WH
+mYDHi4OWsar/4jcqq1S0RZ5lGQWtJIpVXjw2SzH7mzfR9BrD48fgwIrPJkpTXsi5
+ATFoEZfVQluifS7qjg5lPVmRkQ0FvNMxOXq97tyEi8zqeWa3TC/5brUx64aeyAB0
+rokzCaTAHY38r7b8eDIFpOlQXj8CowjbXx/rvgc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c7.crt
new file mode 100644
index 00000000000..242a81a0d29
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c7.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAKWasxMN2xGHyCWP+sEXohZanUU4MA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4yLmM3MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjIuYzcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIW2QjCSqW9RSVtYf8XyuveF9dozsAKdDqN6r9n9OpUrkdozB/tguOPvy+yS
+aHN/139IrP1QYCqaiaUBevUQzU1N7/yYnFXpdGiNUrkWXy6wTSuZhmBm3r2y2XwJ
+rszGz5/uVpQc1njzZssON9Ug2mzxKvZvs4hUXnX2GOyujx0PAgMBAAGjfzB9MB0G
+A1UdDgQWBBSLcQpmKblNBFdAbAfRm3OAg0CSkjAfBgNVHSMEGDAWgBSLcQpmKblN
+BFdAbAfRm3OAg0CSkjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMi5jbHVzdGVy
+Ny5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAHVpk
+qkgLywJFDpCTTt+vtpsaYlevMdrNAKI9VU3F5NQks4goc6HvzsDwttFh1BrWXitp
+NaxEsbwk21lLFTZ7GlzuChFHQWsZIHZDiKStCEiN726fqcjfzYGF5wtca6idD6Fm
+xAhf41BB/O9kzIJasldR58vtfepGXPLJWKTrshg=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c8.crt
new file mode 100644
index 00000000000..8beeada4380
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n2.c8.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUXWB0aBshcvW7Us5kC8nYweCwm7IwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjIuYzgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0MTMy
+MjE1WjAQMQ4wDAYDVQQDEwVuMi5jODCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAr12D4+Xsjy/okhAJ1kDVb/WJ64ocd2GdWQ1iQj3LUrDtw/KFlWwCk7OaNflh
+xxQKC7/Ow2Cjor9D8yj3/arHH8kKYG9pMvs8BTMVLhU8kXCLIziuF5s/fzBNRvhh
+cqTdjcZn1fLW8UVsMybHgdEQWL7Y9pwxnKuzukIga2+lOU0CAwEAAaN/MH0wHQYD
+VR0OBBYEFMJManm4XJjT1UmZ6pOR0RWsSVR1MB8GA1UdIwQYMBaAFMJManm4XJjT
+1UmZ6pOR0RWsSVR1MDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUyLmNsdXN0ZXI4
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQCA1rWP
+pNBDZ/vvZHe4FpXS5jWj1qxlcr9bGr9CCpWtb8cA1CKEi5bBAN6gvt+hoFw6/6XW
+wz+Az3BteusKEFHm7nohr3xswCdffJDXY7olHhNu3j+r1RtW3YXxfMlFsCZxUikL
+zOD5OVDBhNPja0rt4zUzoa54jg0xy+14G/dfWg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c1.crt
new file mode 100644
index 00000000000..ce72a9419b3
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c1.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUeWtVaCz/N70J5xpIy86NU8PUhSgwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjMuYzEwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0MTMy
+MjEzWjAQMQ4wDAYDVQQDEwVuMy5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAjMpw8/41N4mhUc0rfxK+8ykcANdc3iJq9I4vyKR6vTHMJX0Q+kEKLpvN+IKN
+Sq1LmfTJJMJx7vljjK6Euy0BncOFTIq91XehVky/ZPZOrLbJutPbRjCFGOwxdYqU
+WMh1YuniQBV8y3gx/6qn0675EJQoK1iXX5xoe3wrqUTi4+MCAwEAAaN/MH0wHQYD
+VR0OBBYEFEns7Lx7ZFHascuMFwRNx1HgOZjWMB8GA1UdIwQYMBaAFEns7Lx7ZFHa
+scuMFwRNx1HgOZjWMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUzLmNsdXN0ZXIx
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBzLfJj
+Y0VUqP0O+FmSmE8xeWchvSG7XAKJHkHPnUeFJbq/duSHVAqkIDMNYd9YvHHX9/R9
+8OlIfahOMy/j42E52PSmC6KSeotaUhsaN/RJ2WdgTS8+lnIimYemi1CbXpVgdZgf
+lBAfF56ypKp+xZ2gSQEZZdD7bATa45LF5ZyjFA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c2.crt
new file mode 100644
index 00000000000..219424ef4c8
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c2.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAMevBYYMfrY3DQ3H2TBDSH5DKJYdMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4zLmMyMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjMuYzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBALEnh4sMjt8W7vwIeW/PirZad6tqKbiCeGyhSWNL07VGDKUsAfF6RY6voyGj
+Bow/fPxQ7OXjlw5BFEgO3DxlTbxLcNk06JV7d4RrfHhCGF3R3x1L/icTg+rB+QdA
+aMdHAiU6Fme5qGUZg7k2C0JO9mTnJO4tIsL+frPGRFmlNZyzAgMBAAGjfzB9MB0G
+A1UdDgQWBBT9XQWzCcEEuYHJXQVr447M/HqFtTAfBgNVHSMEGDAWgBT9XQWzCcEE
+uYHJXQVr447M/HqFtTAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMy5jbHVzdGVy
+Mi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEABxKm
+Id8s0A6ShwMzQT6C0QfgyYiI/dJ7ghAAg2nJ6P6Gl4WBQNSDkY/UGFXJALIud1Lo
+Eb0x7omu7k8fYd9GpbWzWgNLwy9lRfvndzHbCLmCJjdH88jqvkN+lzINcEu2hjX6
+dEaR79lYBj3Kam9tLQCqRd66zN9/yt1N3oNCwo4=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c3.crt
new file mode 100644
index 00000000000..27727392f10
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c3.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUUzIsCAQr4iJUUIBY0ZWZuZfi8ZAwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjMuYzMwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuMy5jMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAlMorfk1gUwZci3ta792qR6j50VUKQ5AqZrvOXk74eYzfPZiE8TJwnphGdfMm
+8Ru4v04+4pf5tTzrl0L+dKebSLvVWYE+VPz/So9jyb2gHT7/I1ypEjum7iUpSiVz
+M09exmSyMrcyRpWSRQcrMomC4EK5OwDctUv1EUqAlgbmuqECAwEAAaN/MH0wHQYD
+VR0OBBYEFOkY81GYZIxcO6x/wKKrfPah0ThRMB8GA1UdIwQYMBaAFOkY81GYZIxc
+O6x/wKKrfPah0ThRMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUzLmNsdXN0ZXIz
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQAGGvtY
+Byl4t9Jv1ykFwOnKZIBeUK31TxYQ3YP6w7Dodu7HJ9AZl+QF9di3FXuoAvwK8coD
+djuyqvvh6fYOdXKZDG2ZEbGHrQlGV+VXQw2OwdY0r9TwCjLT6MPqJeqiONQ/M2py
+JM+mshS35mZpsD1ZCtbw6M/CFJrMVQMP6y05xQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c4.crt
new file mode 100644
index 00000000000..911e756f286
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c4.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAMasz2/hWiW7UURuyjgybK8+NYpbMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4zLmM0MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjMuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIwFiuTI0adVuF91ltRwyCzA2Eb9fV8JUKmlVXfjElP+XGG2CUerk8H1Ps0n
+PDFBCZB+0VM5BzjrtsEYmuEk7LJDXzoEj6L2MiYKIVia+qxzLvSfbcdJsGNXDrKn
+47sKDrUJbBDVodI43xGCplWyyhf0MS6hMe+7ttwb+LIZzTFLAgMBAAGjfzB9MB0G
+A1UdDgQWBBQJKDvefckZz3in61z5pdM6CpIwYTAfBgNVHSMEGDAWgBQJKDvefckZ
+z3in61z5pdM6CpIwYTAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMy5jbHVzdGVy
+NC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAS/6P
+0hx5NljLIKafQ4/MfompNgk4/yTY2eJfBuw7qdpqdfe1+bd2jB8ptuQ7t+vR8j+F
+42EmDGwZHwFVqr5PkXfhn9Drrx9muSXeXLheZ9FeknvR1n0upZ4KnKq9sqaN+JJh
+BnxpDpp3wLmP6LwWxHrAxWtiCvjngDh/hXx/P4M=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c5.crt
new file mode 100644
index 00000000000..1132dabfb9e
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c5.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUCiG69NDv2GoMmFE3qaYNb/8lYRwwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjMuYzUwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuMy5jNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAm+gpSNeO4opovT+vEOBd34pKfiCaIqoe0D+vR60gB35glziDShITOGMs04qU
+kM44nnv+d/Qib2BdkNlze+l/Sv92r+0DQp+MRzdNE9GkuV4B8yF99hpi71hJMED1
+lkrYRLUiEFUjmHccUoO6fF8BbdQwvD3rBTpAss1nDuO4BncCAwEAAaN/MH0wHQYD
+VR0OBBYEFFT81Tir0l9q5Cr5n47pDeY9pr4EMB8GA1UdIwQYMBaAFFT81Tir0l9q
+5Cr5n47pDeY9pr4EMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUzLmNsdXN0ZXI1
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBeApiQ
+M3HD7EzECcaSFMOhCpgmCQg/fV3gDaKSe8pbbzbSkKqoYsLwQM7HNUV+sEhrl+e0
+G9vR3cEeDMhuGuthVeqJ6jhgqn9vjXL2cLsDzgQYvj5AEOQe1/RfYWVOqYAuBtMk
+M+k7Rwrddd5+Fko2LtNXGskYwv1ExHSOl3MYSA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c6.crt
new file mode 100644
index 00000000000..ab338792607
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c6.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVANXn8r0H2YaPh9YLfjlI7c/QtXNVMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4zLmM2MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjMuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAI9iaWrpHwmXPBC3YhfzkVe10A7AKjRzdo5uv4ra8xQmVzsdk3lQ+oQDYMDF
+oP7rfxtRLzB2Z5l5rChFbkLav+3G8DJ09Vdzs28J9Kxz7N/H9tEiTmgvzdPVBWRy
+A7D2WPPiaHBeIIrtgzfZbHenyxuDxfNtvgvSgUZMEjM7Vg83AgMBAAGjfzB9MB0G
+A1UdDgQWBBSADI6qBveWvxd9C8xucsFtogIDRTAfBgNVHSMEGDAWgBSADI6qBveW
+vxd9C8xucsFtogIDRTAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMy5jbHVzdGVy
+Ni5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEABgqe
+FBbsrBz4276uUtr0YkmUlVUoOYewotLq267YGFH/kQkLJbN/Yvdow++7xn0+W2Wo
+LqkwlMfzZicpnm5TgqKO9SQCXxMonhCyvNIuJgShkADIgwKnLNQq4PpV7gyN+ePV
+RUCAQJdcLMPt5SH+q9E528K28WJ1aVWarDDkxEo=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c7.crt
new file mode 100644
index 00000000000..5aced504e99
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c7.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUXRJ0mqzIAtG7P2+PpLY08BWDIigwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjMuYzcwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0MTMy
+MjE1WjAQMQ4wDAYDVQQDEwVuMy5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAxbb/mneg3oKdKk7tMpcpC+KDBsWWvgx9tKPqHFBWIrklLEeHVA87wuWoXVoE
+moPRmaJkHCuNSUOmNUsw4ZAigdCHLI+Fxgu3RXE5YcOlR/VcfIdmeTOkZTmfkAVl
+6sRIPMARTeQkqaaG93WtXpSFQ+hO3RBIkJ3t3vTL7m7dUH0CAwEAAaN/MH0wHQYD
+VR0OBBYEFL/uRR/fiAlWZMNJZ8ZcDCDLLkCaMB8GA1UdIwQYMBaAFL/uRR/fiAlW
+ZMNJZ8ZcDCDLLkCaMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGUzLmNsdXN0ZXI3
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQA01y/O
+PSsN1yMbI8uj8G8HH+ZTXqvf70DdL4Ujy3t0l+bMUW61ZtPKVE1eoQ8e2Zc7c52n
+uMuLF+ndIAaAg07aAA8ay6vCivSymgzskMfy4qludDAnenbfrK+7+elrTh+Bq/9X
+h6iBhL+cb6ooOJaoynlZyHKP1HY8xq6GYY7K8A==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c8.crt
new file mode 100644
index 00000000000..87817130c15
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n3.c8.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAPLfYPUyngardZMqXbQSc9jFW/ZNMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW4zLmM4MB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkwNDEz
+MjIxNVowEDEOMAwGA1UEAxMFbjMuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIr6JyOARsRn4zJ//TSQ3eMigJDnDTz4qloEcGRhdsEmEkiVxmawSx5XYZeq
+vQIz69axBViHQZEa1emNrgktmzR4swV8wUip8tJhcic7iegSYk40VG8w5YSDfVhC
+a4JEjTF+H/0B61j+Gq81Xzqw6g4m8kJWqWCvICNDo5SKkBSzAgMBAAGjfzB9MB0G
+A1UdDgQWBBRYXtwMkHRZ58jOv4Naa7AkihBRijAfBgNVHSMEGDAWgBRYXtwMkHRZ
+58jOv4Naa7AkihBRijAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlMy5jbHVzdGVy
+OC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAiP9A
+lTjp4exnE8d71b2a2bP5+4zF/yT6Jq6eVKKUi1ChFnGpUQLHaCtEeNMrMusQfDvz
+NYi9E+3TG/5/CDgkimAWxJc/gzTge2Y2HhCWV4Sm3qV2TY5gnqbN4Ib5YQaHcL/x
+1fKEKHxHf+6F8CdyGlMBei1LwIx9iHqWMjuagg4=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c1.crt
new file mode 100644
index 00000000000..3083fbc5ee2
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c1.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUP6Apm4lhwWUMZcX1Sgop10fSuPEwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjQuYzEwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0MTMy
+MjEzWjAQMQ4wDAYDVQQDEwVuNC5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAlusHSJz+gYQ2zUkOFFPijbePcDBt5QT8IQpmrAdQhq+O8gdwPxVrL/ROkAms
+boSiuKqWo036b4Gbro0Q2fK4uyPhfergvJfdbAWKZC3gtCSyx+/36rWS9pxSArLK
+2hne6aYcjhuGlhzcGrhKs5ByEt30RkEK9REwp0M+PGxoAmsCAwEAAaN/MH0wHQYD
+VR0OBBYEFMt0AUJ/1BWNa8n8VS+BmXy/GSYaMB8GA1UdIwQYMBaAFMt0AUJ/1BWN
+a8n8VS+BmXy/GSYaMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU0LmNsdXN0ZXIx
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBhVNAp
+rAoxevBNuG6HP/1CougyBIXz4/hxdEfMr/D/u6kEBXTTkulFbI7IHUvwATz4oKUd
+CNzBQYRp+dcWpvqSL1rgkdxnPkNbdBHr9BEwiyCpk4nQAF12DpPPMxgeeOE2EiLQ
+kTkE00nh6i2cJlYQsriPlQ1S9KUcY70ch+rjaQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c2.crt
new file mode 100644
index 00000000000..d0bb18e84d3
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c2.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVALfLHibW9Z409nWoaPHhXA+o+2ksMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW40LmMyMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjQuYzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKj0cnL86BiN2VBhvrH3XDplcwd8lFAGxAzAfP+Sx1Swqd6y4hZoX2VkJ43A
+uYvJY7aoMK4xIQJ4lWbrvCa+5epbOY1GGg82Z+/Od7mfZppfajCKTAmAIXfaSW48
+V/fRZyYl3KDfP4h5AqJV02wAJ4g5r7Olm74dwAMclLF6FqwfAgMBAAGjfzB9MB0G
+A1UdDgQWBBQ9SpGlYooWMcJYNuTND5SQk6EPfjAfBgNVHSMEGDAWgBQ9SpGlYooW
+McJYNuTND5SQk6EPfjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNC5jbHVzdGVy
+Mi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAO/iR
+mu5N94XQp0J3K5v0ZZzP2jyhpkki746RtHO2NGIOaq96wdivsvqYpDMCI1DXUktQ
+Pbt1Wti4TkmyOXmDQdHtf8pWFHeAPdZgi/g0ThPI8Fz6crrZeJZL9JCj29O8MxQT
+LNf0T/FXeo7EChM4VVekMcv7eJXwKTWXOng6Axw=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c3.crt
new file mode 100644
index 00000000000..e68c6097b31
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c3.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIULVXMkTsJtk6I/NjAm5UONplDpOowDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjQuYzMwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuNC5jMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAlLG3qMUCPi2usnc7jsxRFHVGjbf5+HWY9nWaboIQ1vHfn0Z3m/hOOCvxwaNY
+4RF75V1ZSeRsAKzGeDD4NC1KC2Dxa81elMfbXq6nLDIfh0klkK8lSw6snzpe8NDM
+SJ8agNdr6zLUgL9e3qh2pU1Fc9ApR6+HRXA9rcnqp/xm4XMCAwEAAaN/MH0wHQYD
+VR0OBBYEFCz38GxHKudMx4dyBlrAcIB+8XC0MB8GA1UdIwQYMBaAFCz38GxHKudM
+x4dyBlrAcIB+8XC0MDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU0LmNsdXN0ZXIz
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQCNoVNn
++rZHQclIPn3eB5sFMypQemZSz+k6VCm1o85lCBJnMn7NrR90SFY6PDN2U7WjKLXB
+6Q2+xqneaTLi2zDU5LvbBmRakXHn6kFWU8xVnTWTanQqvh5lqwptQjb33yN+iSBT
+/D7jEcYAcntrwtcel1EjfTbmfpB3UsyG09s/sg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c4.crt
new file mode 100644
index 00000000000..29fc38bbe7e
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c4.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAKdwxZ0iNx1vHQXPhBF0+HxwMwMFMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW40LmM0MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjQuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJDwOCTGpe52Ph9EXMq+Spr7uLi+hxtJFsNVy16vzkSfjaEKhifl95ieBRzx
+1m/Zesn7prrSux00lMer6Gc4BVRtTnGenVGpH3wpG43qBlXvuBtqI5cH740K6yYa
+AemlyS1kUw2OFazToIo5Qc2MMmRxReCBywFg//LtEQhi3YmbAgMBAAGjfzB9MB0G
+A1UdDgQWBBQDRkoU6EfsM98Japt0aiRlTZAV7zAfBgNVHSMEGDAWgBQDRkoU6Efs
+M98Japt0aiRlTZAV7zAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNC5jbHVzdGVy
+NC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAKfU5
+VHQXHnNTvfvzPUD0PDswSvqV3Sp+dujKXX9YcSEtp3kIJzFKDNb5Pjw50+/H5vl1
+Pu+n2nGaFxSHnqbsGGMylzAO7qngaJMUXuFyYHpyxf4dXqu3hjNfQFQaAJ0ggMnp
+WZfyNLA2TO20ptEDa1A5wbLqRu2vLnLeGtyBfqE=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c5.crt
new file mode 100644
index 00000000000..2ff79753fda
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c5.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAON+/VKvMR2xMgnemknulon7vQlmMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW40LmM1MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjQuYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKCP9rT1CKEdFPbGE2ywJgZiX1qf5H36DwokH8diz/XVk/t2QOU7Hqui5HJk
+Q6Du6ywPXOqAIg/Iv3Rj1Vo+B9jcPs/DY0Sj3mKdZHhySaoTHPWjv7mVa/PLfMEl
+bmB4sYkgfotHVxUir3Xw5byGkJ+SjG+xYrMOSktBNph4Zh4jAgMBAAGjfzB9MB0G
+A1UdDgQWBBRrw5xcRVozWKOs6ZHd4Q524MCFyzAfBgNVHSMEGDAWgBRrw5xcRVoz
+WKOs6ZHd4Q524MCFyzAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNC5jbHVzdGVy
+NS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEADiK8
+asbnbUu8Aj6OO+lizquvCx+p1jTHN9+teu2WNtQzcSqDvE7AzvtFQoU7381BCIoA
+IrtCwnqK8TIliZfLYK4kNWAW2Z1d6fn7KlL6HWwtHBy+ht/7jr7M+wcLd78UbxZL
+mdCX4+s0FJ2mfldNe8xq0yRjM0laiF+P3F2WREU=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c6.crt
new file mode 100644
index 00000000000..e22f9161b0d
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c6.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAJ+HlcBtFkTPyQrCCvbdHlBLtP4pMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW40LmM2MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjQuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKiyEVPmc9H8quSkeyFE0GpA1yuRJfDd1OJ3I+ogifTkmZcKu3u1wCbxv675
+xRdpRzCbB8+hUr6ZC18qWUDxXp1ml4iRr8n8bVAmENgJzzp3RLBZROFuwVe2dttu
+n1SMiBlnlcUnmSCX7OCTJWrr3tI0/F8RIdaB+63gf2Eby2eLAgMBAAGjfzB9MB0G
+A1UdDgQWBBSg537AtIe7R0hQVRHdpCNBBw4I2zAfBgNVHSMEGDAWgBSg537AtIe7
+R0hQVRHdpCNBBw4I2zAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNC5jbHVzdGVy
+Ni5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAUdzF
+snAZflUna0f2B2WW03U3sBl5aybZaajWNxH/u/CCnSmZcdSytawJ+iuyuEaLMPci
+zZqgxRVfOwgKlKou6u2hu2A6zOWuHI83LfrQXHNipy7X0pEVX31tgb0yRu4azsRr
+3tm4FOLGjYqkU3LviuukIBSzigcOp3s3DkLI60Q=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c7.crt
new file mode 100644
index 00000000000..b0ec3d41aa8
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c7.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUb4zqML7sOuozKkgpS93QUD40XSIwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjQuYzcwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0MTMy
+MjE1WjAQMQ4wDAYDVQQDEwVuNC5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAjvRiPU8N+9dppeWCZf3gRL7r2afS6iS7YZn3yqYeikXec14GkDotYxR+ZPeG
+3iTwhE73I+iXIScqZmtqk6sL3Iv5Z700w8CBIhLFZP0L6MPDpT0WwBweRzC1BA1u
+Xam3Cwp0hux5xAH49h0EZvFT6bxSVdhrunsWlW1N5vZIOlUCAwEAAaN/MH0wHQYD
+VR0OBBYEFEMbNKUNe9yyOtm8R/QonVKFl7C9MB8GA1UdIwQYMBaAFEMbNKUNe9yy
+Otm8R/QonVKFl7C9MDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU0LmNsdXN0ZXI3
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQAKn5SX
+5Cwk9cXIijfveeJ+vzzqs3K3FBukA1rT+0PrFRT7kZ4Zg5IeUwCGnBVDKf4XoNyO
+Aq3ads+iVOOVn8GvlMacvh76YqDmlgF3TqX3KJRm+NEVHwonwdaxXLMi+iK7sbtA
+af0IE1zsgddYjz6yQ4nbFGKjji7U6MxwcEKRRQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c8.crt
new file mode 100644
index 00000000000..cbd83c42b52
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n4.c8.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAP9uvL1aQzoHJdqBJ277FRrW7RTYMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW40LmM4MB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkwNDEz
+MjIxNVowEDEOMAwGA1UEAxMFbjQuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJ1FfrHkc7tQtArp5NrVzVl1SiHNyGtT42dYoceXYjfCrKoF8yT7VZdgSePg
+yCFvMlFanq2tT/QHG3kKNW7cz7wK+Y1BSBQMWSPze98dCgRStqx6eu0T1IGQZ3/H
+5Da4ejolu+g8o/G3dUez8hqxuoc41v4JBAOVDGNlIdYSlGpNAgMBAAGjfzB9MB0G
+A1UdDgQWBBSfXMfH8Xf7zowDOoCEMP76iAtYBjAfBgNVHSMEGDAWgBSfXMfH8Xf7
+zowDOoCEMP76iAtYBjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNC5jbHVzdGVy
+OC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEARVu0
+SuTODyHIHTuHOByZ1h4UefWpYn64DwsrZC1wElUimOjcxxGhRKlgfM6aElDNLAOO
+hcEO4KX9GROFzzQ+4ZvifXWU6Wdsrmu8Y1RXxqQUhbzlQok3rEJE15TSvTspMs4X
++7iDYZ8wvWLnZ8mf8IoPEb1r5uoJOkf00PxYLv4=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c1.crt
new file mode 100644
index 00000000000..dd3475e13b3
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c1.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAPJ+UHse1NzYUAWE4qVvMbBC3/WNMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW41LmMxMB4XDTE4MDQxOTEzMjIxM1oXDTQ1MDkwNDEz
+MjIxM1owEDEOMAwGA1UEAxMFbjUuYzEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJNmny/UimTv9fGqahCbXJ1Z+o+ShVYIsC0Z6g3tDtMGigLgGrVJEbtehE1E
+Is/YFCdy5RQP+/gPuqQcIFY+a4d4oXkOf559+Dkj+GlY8DDHIxSYFMT1b0cUdaY7
+KcSgbDHcE7ehFwYO8iU1iOC5PdiNFsur29CQH+fLMkGHeeuBAgMBAAGjfzB9MB0G
+A1UdDgQWBBR7PXi1qWwEhdtmH36E3IaLtwT33jAfBgNVHSMEGDAWgBR7PXi1qWwE
+hdtmH36E3IaLtwT33jAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNS5jbHVzdGVy
+MS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAi6Um
+1XXvrakSEQLnFHYwVoTGEvQOX48J/W/sB5CYFHunn4S3I1h+uY1U3onR8vkHGrj8
+ClfYuDeEXv3UjmOulAb/YT5pcSjXroYRSQZgkFTlbMmoaIyNVOPw2jXRm5l27CjN
+lWKnJAu9OQEPPkjb9SSkqcazgPi5wmAKtnRmEaM=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c2.crt
new file mode 100644
index 00000000000..82d7e9c42a1
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c2.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUAjNAqngaZ7ks/XGNv6f5elfJU/QwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjUuYzIwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuNS5jMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAwIe2m8DEVRgwTgfukT218TRvgaJ88GO5v12NUIg/uzgq2ADAIS4lynhz5mzs
+dhcArzWFCz7MxP/fMxfwzRP7dNm2pjz57+DdUUSpPrBCDL/3+JwHWevd6LgMmgLO
+SohsJOZmWe5PUVMiP8/sluBb1+63v0e3iDNUXreVal0xxF8CAwEAAaN/MH0wHQYD
+VR0OBBYEFOOs6r9usaTHZ735J+HCRsZb8mDmMB8GA1UdIwQYMBaAFOOs6r9usaTH
+Z735J+HCRsZb8mDmMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0ZXIy
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQA0lOcK
+U1O9pvw+GRqtodI1fNWObmMewUc482JWTCA+WVam4kwnXF0zsCYePdAnlu3eCBV7
+TAZeSIVRez6HGomSFz1OqtQOSOB/2mg4P+hNy+VIi+RoB7BPtQ6H7JBrTZ22wMcp
+7CzrUiOStlsuqx2K/euX109WmRLGy2Brj3MxFg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c3.crt
new file mode 100644
index 00000000000..40166d0c271
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c3.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAIyTRMpfs9Nfo0QL/yDgL0L8eeN9MA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW41LmMzMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjUuYzMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJOBFDvbKzWo6MzAQUVb9t8ChihkEGokN8P/MdUkg07CEHIiTSLMj0FvfH/J
+V7E4YtiELUY0grTcWRln7Q0bt7fuGtC97TxL627dx/jiuTHCG0tko4bF/KyKiRFG
+O1CbXQ5tQzvDom59FNQzk07HT5aFt85Oxhqw6Om8R6YraLclAgMBAAGjfzB9MB0G
+A1UdDgQWBBTlHIVNp/hPa3SPVI3U9cusa0lKKTAfBgNVHSMEGDAWgBTlHIVNp/hP
+a3SPVI3U9cusa0lKKTAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNS5jbHVzdGVy
+My5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAcAdT
+R+l3uo8EKz1p9PxiCB26VI+1ZWVmyD4bKAjAgzYCz2HvNAbkkVMW5tGfmzLDuZm1
+pxpIrxi0VFeFhZyzlgF/umcPjr88MXWox0QNYLMiYFIxQQMJljglDxwyO9keVLoD
+VZdIp8pZoaGs6tKQDyzmBh//6deecyNDNubfJb0=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c4.crt
new file mode 100644
index 00000000000..5f9167b441c
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c4.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUVxoYfxLb1GFz1joNjsIRlzhQ58EwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjUuYzQwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuNS5jNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAiGKK1GCMeyJzrzzi4pNaCWqd2qiFPISAANTh+laKkKQDLbrLo6BNfv9Ef2Zn
+pFO2JXWbDzNd2UDA5wKjlNPacFvoWbQM+pydH5KOmQ0tG5AkrWgnMSVyZ4UY7tUG
+AnkMe7ZwtWWETVTOzW478mqV3TAM9FjIPmUFuIyR40hF7EkCAwEAAaN/MH0wHQYD
+VR0OBBYEFI+J3qFQpd1bJy1q/oww35Dt/lB+MB8GA1UdIwQYMBaAFI+J3qFQpd1b
+Jy1q/oww35Dt/lB+MDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0ZXI0
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQAqxVEf
+8W8V3ZHi5DkIxGqZoRN2ukHG1UVOvxItbhlbvdYN0mrFeGl8xzWtP4wYHgiGBs6D
+3lzwD0cj1hbUi5Wg5kt8KuGqpAiELHKLbdp7AFRrAPTkLC1XNWEMYjZcbR4XHVP8
+rMVVYK0QV8ycLsotazvpHbmT+DfXRDyqFkxAwg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c5.crt
new file mode 100644
index 00000000000..0c6f69a17e8
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c5.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUNJzE2lRQpXQl/GqdwDQi0JvuPqUwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjUuYzUwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuNS5jNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAu23ACgbulVvEbb1O1WLxhi9/KvDXyqPekjC9Mfe4PQ2yqUaoR2XxKimbChuE
+Rzbv1Ggt/msDngoRxRqgSM8mjR4I98YhDFY61IIeL8OmnbyjfbAXOPS5jy+qA6WF
+jlqSBFDIld2AcFJWdrFhsdq0+A7Q/2x4YuSk48SFUr+aEacCAwEAAaN/MH0wHQYD
+VR0OBBYEFB3l604mCVN5uOPCBWbsOdmi9aEHMB8GA1UdIwQYMBaAFB3l604mCVN5
+uOPCBWbsOdmi9aEHMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0ZXI1
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQAt5yP6
+J/JgBzJpYmX7YQp5gkaCZZDK07zGl0/53HDb/yiSxeiZcDuqwqlpmIeGdCbf6J8+
+2aEdC47+82TQn9ugEudvLUfTY7RDVsKW6KAeD8UJhQH3cjARxlJlwTELkS5QqFyC
+mM35puJoLctM3pxK0iqHKSh8wSkckARDYP/2Hw==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c6.crt
new file mode 100644
index 00000000000..5cf212017fa
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c6.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUDJQ6adYh3ugguVhpwXAztpir0/MwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjUuYzYwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuNS5jNjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAxUpbKRNQ/WxzJj7oYFBzeP3/JwtVTaTqlJexfKpEXAGlTXrUYRVyZP804p+2
+Dc5sAFEFXwUcmYgVlLCj+mc2OGg9Uv6EyaT1Bz0r4oEbIB7ePBiefx41i2Rhd6zy
+3Jg164hGnrHzmOdqhz0hjKxUAgBFzEtfx0URtIpscMefimkCAwEAAaN/MH0wHQYD
+VR0OBBYEFEyrP19EhCIvYsJFVyZPZ/2Uis/gMB8GA1UdIwQYMBaAFEyrP19EhCIv
+YsJFVyZPZ/2Uis/gMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU1LmNsdXN0ZXI2
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQB5b061
+fk5o+h+m/mOR7pi9TKwKnseiK5P/N4Gv9WuAyN+edee74+/MfWmLtGtTyeZQ3XXb
+Twxfr+UvHzHDN+0QHuQIj77DBDTxfULKF6AXKoVX4NGABDdhKCkxRXjdqmq19G+q
+upeZXyel+qvteAH16mzrVMGu59gG2IGz5+RMsg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c7.crt
new file mode 100644
index 00000000000..e928f5fdb5d
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c7.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVALd4gLmbZw/Ym+O+RgzBT3rore8kMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW41LmM3MB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkwNDEz
+MjIxNVowEDEOMAwGA1UEAxMFbjUuYzcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIOhA7sGBQNF8E/f+5jB7Bw3oya3w6vHWbGJtPeAkA3HXQWtw0cR7h75TxyP
+tsjYa3Pi7CF2tsV7raZhX7tVJtwVq5753TpCtBVOVXcjXhXR/Hlo0+EFVa+l2iOf
+OqiGn03CwILdpNNab6HGIQGHe3xsk2GLG1uMI8clz9uo7KRvAgMBAAGjfzB9MB0G
+A1UdDgQWBBQkRUJkntKPJPIaIRVydRbQeAPUCDAfBgNVHSMEGDAWgBQkRUJkntKP
+JPIaIRVydRbQeAPUCDAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNS5jbHVzdGVy
+Ny5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAQJlL
+BeTrtZr94sm0hYdpl54dPJciBtyWi8XMw8SmngyuDaQaLe9kpWAbrsDX46m4vXAd
+FkWyRZexDS4R1mBuMHjcj6hSTAFOiy6ypdQvfCuzvLxLEq9NXq/4y+2pkp8G7c43
+Kcnk1o3P/BqFoHcwKV2oozDgIYawQxvE1fIXzHc=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c8.crt
new file mode 100644
index 00000000000..5cb3781514f
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n5.c8.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAIQ/OUvFomO/a5eOYDI6WJ3HM5VuMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW41LmM4MB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkwNDEz
+MjIxNVowEDEOMAwGA1UEAxMFbjUuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIJQgqB0qJj7Db0GiPnvl4AsKtFa5DV52/DLfqri1FwhOcIVhtnLXFA2wsUT
+/g7aJ/b3tZszfTwG0mKSmNS9voTlpaLAb6Gn+vq6bBpgvgW3kvcP+r5lxMIGU0zs
+8yC3hqXwUOX/FbWZzd87eEiM6fDfhwg4JbP7nSk/JX8MUEqLAgMBAAGjfzB9MB0G
+A1UdDgQWBBR9W6ltaRBtK+Q3dWeXPFp5cwdSFjAfBgNVHSMEGDAWgBR9W6ltaRBt
+K+Q3dWeXPFp5cwdSFjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNS5jbHVzdGVy
+OC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAW0cU
+1UW5gZip0ShYRi8iQ4CiXreN0BcR+Snts9b5BCf/P4mjg8x+55Ewz/+sVigyI8cV
+h1zgMKb84g3bnxG9vahb1sA4N7q4o+DDgDLCoMNUUgyuLWa+TSdXVfqDONikIosr
+fkJ03rnOg57QvOto+SR2hiIDC2zyHif6wUn6SOI=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c1.crt
new file mode 100644
index 00000000000..5c822ab56b2
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c1.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAPfDYqSl581XnG/kfEiDs6IEfKWnMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW42LmMxMB4XDTE4MDQxOTEzMjIxM1oXDTQ1MDkwNDEz
+MjIxM1owEDEOMAwGA1UEAxMFbjYuYzEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJFHcBG8RLrI/ifvapZW6f42HHBEf3U2FFqAwpZMX8IDVDddF7OQNPBEUrNQ
+2dCFX8pkcEJcnnIlGP0NDN4JEV2N71NjN/WTwBFoHDAXs6e1aKaLRv+Hz5xqIdtb
+5QfqjbuQsHFoE3HVrbDZn60pENN6JFn3ddt1nGYamMRycS/7AgMBAAGjfzB9MB0G
+A1UdDgQWBBTLEf5TUnKZHJfUMV/CQDFT+5k9FjAfBgNVHSMEGDAWgBTLEf5TUnKZ
+HJfUMV/CQDFT+5k9FjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVzdGVy
+MS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAcDU1
+Z/0qJCuqIXugAbeBQLBiDwWpsPC2AatBslCaHm6prnA4QCGwZ7wI/FnunMzmGf13
+VvFEEWnW786+mh6WkI5iEba7sHf5vWmKO9rBJHYm3bcFnh7A2D8hvf7DwFNG3Kpm
++/iqy81ag/BOveDlpu5fJPzAvJwTpVJ6ie0XQ8U=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c2.crt
new file mode 100644
index 00000000000..9cf522d3ec2
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c2.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAKSYs2CPma3+QQ1KFujo0UdYTPChMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW42LmMyMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjYuYzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAMJ7+brk5AZGhtD9dMKVhkHCmsAhULpd94aF8nK50Vw/Jgf/SdE6yYePrBxB
+C+Or+o5+N8Dwe70escEOH6o793gg8yBWyL1AagoJZDV/+A41cxropz0jVW5X4SJu
++y9tEgVA7m6cdefow1SG1EiMLMtEHyw5wKNmUKrl544O+MQvAgMBAAGjfzB9MB0G
+A1UdDgQWBBQGIpG1JOyVo9JCyp1/h9yMhHE3lTAfBgNVHSMEGDAWgBQGIpG1JOyV
+o9JCyp1/h9yMhHE3lTAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVzdGVy
+Mi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEADfpT
+pfnIHFoNw5xvdxOelm5S3CKOk7lBroCjnowGaR59D9yoPRlyaX+YaRO51Mv0rzvS
+3qJjjrKlCXeGNF9rKU0OlM6MVuGmlMhgj6nv+0eX9ntHVYzSvbBxXUx0/jvQZYV7
+C2t1qljMjpFoi++p349dWsMfosx8X97HhXA7P8w=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c3.crt
new file mode 100644
index 00000000000..e6347d23ae6
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c3.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVANfjBjDTVL4+UG3xEGlDqhK/fhH4MA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW42LmMzMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjYuYzMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBANBW+tmJaaum3CPc+7wj+qrDkbvuDue24I2Yodp3HSsChx94KmFDYhGYuRWw
+sDF3Cu8iPyUi1xk4fCQallLCzkwny9j6dljAHtAYkVfNP07WBdPJ79IWUn4qbldq
+LTam9ZiaQZ0jPtHa6PUmj8doc0QWM1ySfJcHqCP53GkqpH+vAgMBAAGjfzB9MB0G
+A1UdDgQWBBRiy14zafEFR9kFLpd7PeVFrLdKUjAfBgNVHSMEGDAWgBRiy14zafEF
+R9kFLpd7PeVFrLdKUjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVzdGVy
+My5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAZueI
+4pUaJEsWQSdPFg4L64T/ec0ETzolzIDb/uxwCBT0RGHRP/94x6o5EGUdA59V2PMT
+5jWOAfa5TgtZYuuAXRyB93Z8wSdTpeHRyxNiVDCRy6Jou28VDIRpFlaJABe7ZfUF
++TEJ8FiDyjABXkUw6TkIIuGkKaGO4SNCX89P+i4=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c4.crt
new file mode 100644
index 00000000000..ba5d4620dd1
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c4.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAIXNMMJ8xgAMFoITRuJVgQZCsNEAMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW42LmM0MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjYuYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJDY20sl1QeuOSxilJdb2r8PygM/o6EPlIJk/NHc6Lh1VG2bxqsS091jCp1U
+Y5uHdynMKXxVhgbIG+rKHgP67rh+3dTWzvThWDMZ1ljMMpdf4NNH3caM7WdgPzj6
+FpJbuEevBnNp9ENRjKFv8DxUDiJPFsXcCZ/sGuK0HUZSzla7AgMBAAGjfzB9MB0G
+A1UdDgQWBBTPFm83nd3zU/X8KaQpSIF8w8njkjAfBgNVHSMEGDAWgBTPFm83nd3z
+U/X8KaQpSIF8w8njkjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVzdGVy
+NC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAKAQP
+iW5nHwgAXy92DaO4eLdzMuODEMgR+w/qSkMw6kaTyD+ZjeyTjlDbldXF5bomQmnR
+w1/90j3MPHoelX2POi8D2BPT350hSXouts7meM55U8fnOHXMLb7CpbNO4TTdYLIO
+2+emw36SIIxVBRz+T+7lB7532vM6TuJN5AsW5kA=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c5.crt
new file mode 100644
index 00000000000..026d31155ac
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c5.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVANAqTNvSXNb+QuG2Dty261T05fD7MA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW42LmM1MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjYuYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAILKAZL8kVxWDh/9//AAeG5U/NF0iQBSruy/8x+CA2yzV6moe8V8Woou7AH3
+ksjTpg8NyWUejvC2WQP+dqvr3+t1XhAuUdpYfcRVg3zS4mFcg2KGrvnVctXpd7Xr
+/L03FIEpaQhUsw+xKrd9+d3VxQMxFyNWAHhB4/rRIqWNjfh5AgMBAAGjfzB9MB0G
+A1UdDgQWBBR+wkLQRaVnAEyo6Ign+W/48tJpWTAfBgNVHSMEGDAWgBR+wkLQRaVn
+AEyo6Ign+W/48tJpWTAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVzdGVy
+NS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEABjLS
+Ws3YyRfF4XhvveU82BiIKS0B0hH5P/ozXiJYUjBZxYc/U1XZR6m8LRQLCfc/kk+S
+KpZgizFPsJvaqxoEFj9YgDFraMD/3dqd/R8GiCeOQYf+LRXSbG+eHnHk9ouzqciU
+kZXeeU0dnM9aVlBFrjlQLk4E4GQhdTZGCxXuuWI=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c6.crt
new file mode 100644
index 00000000000..ec90f278984
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c6.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAJBP/I3D0hBi9f12S8zW653VRl2iMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW42LmM2MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjYuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBALAFA8o7mX4GYsexgC1JaQzogoJzVK0XGeeWUMKIU3kjhfjezxwY8Pqk1bCo
+hm+WTdhRUxtO4Ku2AMz7FaOYnhf1gAALT87M8iEQD703Fd83jcmrAuWG0zibkzos
+0xxzOrg+yMU7Tj3YGBqDKuOiXR9vNR5vpscU81bg4ZTT561DAgMBAAGjfzB9MB0G
+A1UdDgQWBBSQZ4R1AxlxN/+tAONyY27r6AKU7zAfBgNVHSMEGDAWgBSQZ4R1Axlx
+N/+tAONyY27r6AKU7zAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVzdGVy
+Ni5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAXwKj
+9JQDAud4CMyHcSz7SWNvode5Pr+1VO8OUAP2UARgtiEzV+ACIgXsWMKY04Y/uP0+
+0bWJv9MRUfw5jIK1Q1Rh6fjrfspL6uU9PidXDxqlfno7YybPCj9IUeJDImQC6LrT
+0OQbhodDwWhFXP4ibbk/tCbiWX+fS7mBThIWZT4=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c7.crt
new file mode 100644
index 00000000000..ba90a4453da
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c7.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVALhovlP3SbGFE87OOAIBX/CaSQaRMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW42LmM3MB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkwNDEz
+MjIxNVowEDEOMAwGA1UEAxMFbjYuYzcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJy8A2khQkFtzq1bi9E8sSKSrJ/v/sWAVASrv8qwuiyRh0F0sxp6KgtJ4ogp
+iI5WbhbIoqWqjoDwGgGvcvf24m+/sr4JDdKb/ZyzkKGOLhLXugQwZABOCPf54DJI
+As/JqoxQ/XhbMPhqLTz6x7qPLj3Tdwybsbj85nZyedkx3gyBAgMBAAGjfzB9MB0G
+A1UdDgQWBBRq79jvLNS4zDUaRG5JNpPgOqXlWTAfBgNVHSMEGDAWgBRq79jvLNS4
+zDUaRG5JNpPgOqXlWTAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVzdGVy
+Ny5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEATtla
+YQx5JvRrZoMhpXYTb40/mFNgnCdT4YktqAL89IrjnU4Uc0xZLNVKt+4wCAx4Uosw
+wT/aymJY/FtwEpTT40l9jYxMSYVFLTiheDSgBzWUHYKZQ6by72ibUzWf7gXALRMV
+pu55YQZJF2ImsjH6gJRniJ07ma2nDHszMi7NWJE=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c8.crt
new file mode 100644
index 00000000000..74dd306fe34
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n6.c8.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAKF/pqC6jeqYbOiIgDBmcXZgUzERMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW42LmM4MB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkwNDEz
+MjIxNVowEDEOMAwGA1UEAxMFbjYuYzgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIMcNI3+aYOuGJx1YVq3VntERfFqmnAsssk9FiJMCzbBG2yD+hPlrlGcCUpG
+fTBzGEpvdd7ftSoy+2SJv2tercjCkg1enCS/hhnUp96NmUPm6yq6XOV6ICtef0hU
+VcuNnXwJitsPFpVJbNmECNE7EI3au1JOKXBBlfRet7IlXax5AgMBAAGjfzB9MB0G
+A1UdDgQWBBRzmA0meyNb9xdcsfCBrjVMIEyM7TAfBgNVHSMEGDAWgBRzmA0meyNb
+9xdcsfCBrjVMIEyM7TAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNi5jbHVzdGVy
+OC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAeNbr
+Fh4rvhqkDxGYUdKzTBi9BcqpAPtl5YiAE7++vH+/kcCtmNppimggFzAxIUPhAdDZ
+QkpmuHX55AGsZf7PdHi/N3BjyB9d3EVEWItV38xGSsJylNK6VF4HDSWtvSDZlgSj
+sQ+m2kbZOICzFodFo2tZ+CfLJWHm4BekVeYC7FQ=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c1.crt
new file mode 100644
index 00000000000..3f67ed8fecc
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c1.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUHFRaZgHge/5D2Djq/MM3MhXtgSMwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjcuYzEwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0MTMy
+MjEzWjAQMQ4wDAYDVQQDEwVuNy5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAtut2Om5X3xl8drxF/Jf/qq+xPYYGs+soYtJM5qAwkC0NGQwPCIDw0pL8hpuJ
+XT4WrtGmADZ0ERvPULGTMcBVzmDgt5KANUT8kt3NqzdDS9PXj3VAYKKuDZ6SdqqW
+7dEKhRmZ4NPERtHA12dYvBgHmMoiWOI+jvas2PvmJ0/dId8CAwEAAaN/MH0wHQYD
+VR0OBBYEFMcRlGJupnRk/6cjwiEb8f08SMxPMB8GA1UdIwQYMBaAFMcRlGJupnRk
+/6cjwiEb8f08SMxPMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0ZXIx
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQCWG5eE
+eptDX5VWR8tbmvciCAt0pEXCO0y9UIflCbnCl5LaaWCn3Dg5LzrPTQxZryksuVSV
+w8RAHUqG17Td3UhB5mgNdOD8MZMoSanO3yFDX+6wZ2pfPSYnLUVu8UdlgTI7p/RL
+r7+PWUgXplJVWpME5FZzVBuC7Rz+n5eaDQzVlA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c2.crt
new file mode 100644
index 00000000000..12ae16246e3
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c2.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVANLcg7s67r1TLdqNOBRZ45hhVL29MA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW43LmMyMB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjcuYzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIprTC9xhz2JYqSV6b7jQrVBeDS9KjkTdYigPMEnkBCW+Gv84TxeU6gXfyMX
+dDmL1A9nbKhpkDYh76FKdd7Ik/fvt7Ixa3RNMe8vdgMJCs5dog7IzdIuncSCGhGK
+VX92FQzja3I9JG2/jjwRtuvKbLRDX5bk24bkyPEWid0p3tsnAgMBAAGjfzB9MB0G
+A1UdDgQWBBT2lPX6qZfTAO4kua3T9ianDXkCOjAfBgNVHSMEGDAWgBT2lPX6qZfT
+AO4kua3T9ianDXkCOjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNy5jbHVzdGVy
+Mi5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAaeyI
+QHWlllHZjZ5M3zy1fG/v7gH0uVWDvdmcrchvYRPJw99CDXUVigDLYD8470BwUqaB
+tygQozU65Y/jazIge9q53REAw7812BXO4lGUj820CxV+KHjjbI2+VnUVDZguUBwP
+ftjrG9lhWAt637WSdShW/Eb5wFSj/MnYY0Ilvl8=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c3.crt
new file mode 100644
index 00000000000..6ab5f2e7808
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c3.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUAcrmViyO3Zxe2UJugNb8VtZNomkwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjcuYzMwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuNy5jMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAjOfHGF/Iku2fsDm+qYyGVEd8jw1eQ1PGVoaG5cTWy/H4Ho+CRB4dldki6b6h
+9A7RW1qbvZJgsdeLBj42tblU1nOYnF3y5SNIcDhzxs79SjNxjNIHgdcjeUR6pLMv
+DBPk+1dXLgoHMd08Un8hanIK/NA8ZgP8j2j57xS62hFGiHECAwEAAaN/MH0wHQYD
+VR0OBBYEFOPlr+WAnl/xLz8B0S9VQPl1+XrXMB8GA1UdIwQYMBaAFOPlr+WAnl/x
+Lz8B0S9VQPl1+XrXMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0ZXIz
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQAoWtAw
+kGlOpCoGhgVmws1eG/47m0o780t+Mq5Lh+IhooviwvaHGlSJfWieOePuiXeLyeb+
+dXTKkgxnwPozNh5lT6X15C4XDIMJ/T3fr8Ggzi+4n1tY7MNW7ll3pdGFvoiKaSNN
+2gQ8u/UpR2Dv2b6OHExiQP3jy/2mtIAQOQ5fPQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c4.crt
new file mode 100644
index 00000000000..e5014272b86
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c4.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUCFu9yiqlax/R6J1jzPe0n1gF424wDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjcuYzQwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuNy5jNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAiPGG+jtQyATOybaNzp8DBRK4rKu6Fs4YVRVanfCB1I3FE8YRdh0uyQQEw4AN
+gxwaJ1MoXHMeXhcrjRC3saUgHeexKy22sn0YKEDTWeAKVhg1C8BppXRZTGp4UwhR
+xGdgQ1oFLjQn+NcTUo4SxEEp7aamFFZPq11YtYsp2sbAgVsCAwEAAaN/MH0wHQYD
+VR0OBBYEFDIEc9vl3VibxzWsH8wfzm/XYh4FMB8GA1UdIwQYMBaAFDIEc9vl3Vib
+xzWsH8wfzm/XYh4FMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0ZXI0
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQAfV2qT
+G96FWbvq+o4zxrW6TVAlmFQ2AWcu35JcD9O9kfl/bd25k8mhsac1P/cIPRxKcFIN
+9EicJpp+EQ6tespPU5xb74eoEro9V9cflQig7P1xmiqVitmxN5zjJBWowOoPeB56
+zx/f/byUY8MJ8t1pAFLoeYCAOrD4eKv2eGpB9Q==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c5.crt
new file mode 100644
index 00000000000..01bd3a9713f
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c5.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAKI2zR76R0ojhtQ6/nGpY/yzXCoIMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW43LmM1MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjcuYzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIxI/vm13r7qO0JHwIU5qFMH9FnANuPqUFnDaxM6uircaa7I4LwxKMp0SSYJ
+Lh4+ThihGBOk8GofaFj80UwQMI0s3yqxn1JaK+DPvvStV5Px5CYyWHOkzLf6Qhh1
+cGPRrsZrrYmp642NAQWm/8v4SV4BmAzWuPUhjfM+k3FnXbF1AgMBAAGjfzB9MB0G
+A1UdDgQWBBSX8uUfOIjJpIqow4083qlVg8FrXTAfBgNVHSMEGDAWgBSX8uUfOIjJ
+pIqow4083qlVg8FrXTAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNy5jbHVzdGVy
+NS5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAiXUe
+wizWQNa6GwXFLFZOBPsYCuVJPepjy1Zu7AWuH9WEOQk/QhlVc47CigYnt5LN0H9k
+OYrGMugwt9MydZvujO7K7Vya2AmvGXtc4rzBZhSzzKw2OqCyebV4q1BH2NPTzq5E
+InDLZDgZ8ClZVJEoXKlgHGetW9nwwplBHCN+Qxs=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c6.crt
new file mode 100644
index 00000000000..a46ad1772f9
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c6.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAL0x6vL81rrpGoM8JmeGDFzfPEQZMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW43LmM2MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjcuYzYwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIu8u2hGHsJKq9o6VOKcApMaSDf+rjr38JfwCNgD2opjq20qORPIcrlrggJ2
+bfxE5o3hb3bdTCEpY9gW8X8IRwwAeqgB9aNLfIf5+RoxpawNRLJDQD8RmqONygrB
+YpIt7pVkDLHRnHqmJqnTGJMGbPfenUxHzp+rruKzShdN8AOPAgMBAAGjfzB9MB0G
+A1UdDgQWBBQ8VNuo2DOKDS+BMuRuCDxohRSFsjAfBgNVHSMEGDAWgBQ8VNuo2DOK
+DS+BMuRuCDxohRSFsjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlNy5jbHVzdGVy
+Ni5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAgzC/
+i2TQMQEMbDRJew02HbwJyAVR4v00Ep8/sK6fgzj0pB3blUgI1CFhu/iN+rbMkLe0
+1IFgRbJT6xhhu29TCWWC64uggySFWQTwujyphu4ATGgS7zJF07u3fUDB0JEtFecb
+UeQC0xwkQUk0RBnnSsakhfAGQ1iDi5/TPA31irk=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c7.crt
new file mode 100644
index 00000000000..c1281ce2b0c
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c7.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUSDyZ1S/oPMJsyaBKt48INtI6P4UwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjcuYzcwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0MTMy
+MjE1WjAQMQ4wDAYDVQQDEwVuNy5jNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAoN6Ca8GpbkzxmORqC/sl3GucqCU/ha1ToDUuJxwzS6QTlJJ83DFbqyzPpIxx
+5YAhYiEfruoIVW4hF6L2KrQbKfAVWsfWHFqBpMycmy64yFCOK91EvHJ9Rs75+Klo
+OtSHgB5d4akgKOOBVyLHGeH3Dyl7nrUfi6FtCyfVCAjA8VkCAwEAAaN/MH0wHQYD
+VR0OBBYEFL4wJd/SFWld5TliWX3H9JPUcTD4MB8GA1UdIwQYMBaAFL4wJd/SFWld
+5TliWX3H9JPUcTD4MDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0ZXI3
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQAk4x86
+/2n5y+Blg4FkJ9tpWX+nfkJa4SLXINfJxX3D1MNBXIkNlzPSC96XZ4b1zkdiZVTi
+EZiIsEwxU1EVjvBYmwGqfLjnqSzNYxl5yR3FPUC1Nhyn9pZ2nieB7tuCxwsrJ1OS
+s4xZjO8As7AYNUpytRRYvx8/KmBfZEW/aRHEcw==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c8.crt
new file mode 100644
index 00000000000..3e32ad64669
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n7.c8.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUKgOBruyfZwrIdrRexXAJ8NwVvJswDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjcuYzgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0MTMy
+MjE1WjAQMQ4wDAYDVQQDEwVuNy5jODCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAkRgHBQ5c5YTSDcgW0Qm7ptHs0LIp1kqBmqFb0IBRSOwkymlR960ObUpGY2qf
+xxEaaMWRsa3HEmx/5xVHirf1ozhh0LGQwI6ZqBjwDLUvpMGD+Lrl4ZzGIOq0GuMp
+QkAF7/gV3316Eu6DJebZ7+REFChgBCeWr14jYrWUgsl+XeECAwEAAaN/MH0wHQYD
+VR0OBBYEFNQ7qK1CaJfgGGralMDWPU5jCRWZMB8GA1UdIwQYMBaAFNQ7qK1CaJfg
+GGralMDWPU5jCRWZMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU3LmNsdXN0ZXI4
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBXqo24
+seeiTtrmmzceAHa7ufi/F3OZ/aikFAa7ZXRgGf7bwJ7dSJNDFBsbhkRnvypWMKQN
+Di9cgsNiIfLzrVAt8VKFfUQwIvw8MT9Uh82lJ9ZqdSR9Uli3D4c2WoIhz81w7CCV
+cAu+0WiDoKqszaxiyxAt9vhi4Q+rV7KrTSgOnw==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c1.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c1.crt
new file mode 100644
index 00000000000..1b172d4bcc6
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c1.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUQK7PM3T7+mYy8ElPam9Rp233WEEwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjguYzEwHhcNMTgwNDE5MTMyMjEzWhcNNDUwOTA0MTMy
+MjEzWjAQMQ4wDAYDVQQDEwVuOC5jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAgXuRBm6AhPl/n0w+6htbZqVgDzHBd9Cnp13KVWFj/aRR2v6ppf2/ZWSPDAp3
+zcZALQrPOnwlNcAlTdoFYbTNhdiciWb3+jMNSuwZaiNODykWoVUXeF+dHsWFmSje
+QydkxPK8AfPwS9/8/wTvR2qjFPzIKYk/JPubG07c/BxC+QcCAwEAAaN/MH0wHQYD
+VR0OBBYEFMLuWtBmdv4emh//95cK1tzKVxLVMB8GA1UdIwQYMBaAFMLuWtBmdv4e
+mh//95cK1tzKVxLVMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0ZXIx
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBqyT1Q
+NDOp5FDMKVowZqJKG5UqenIZ0FHk5YGSV+TJnLE6LdGLsrEie+zBirY/rWYH+vJs
+Ao3HrA/IM1hGVPAZI2g7nFsokqOtTNgrm0/SSRuMSf1J82KhrG0cHcuXuMb0Z9PG
+d8yP0524XXfbbwN0fT/AuEWa3hmS2NWXiJOoKA==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c2.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c2.crt
new file mode 100644
index 00000000000..8c3fe5249b5
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c2.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIURuq55mbrZcWnTGXp61EVqnrGxngwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjguYzIwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuOC5jMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAtfvCH7wJN5iSoyeWtfeJFIs3BrCtS/cb4LI41nam3g9T0Ag9WPhf1aPP5QBg
+DQ1umY0kuZEhojduZHgZVoG7mNVNTgqSJCJKooKR+SrQ4gqaIlgIwSpKwo4u/za0
+4p1OqRhOJajOMCuC4zEz9yPt1YAfXCkYryBlne5m7Y+mVncCAwEAAaN/MH0wHQYD
+VR0OBBYEFLpfZ8SVBLNw/xipDeUe27M9REyEMB8GA1UdIwQYMBaAFLpfZ8SVBLNw
+/xipDeUe27M9REyEMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0ZXIy
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBODSa5
+2GRYIcw6npTyw+Ds3UhiluYMpYmopi+igLRRndBVk1Z9gCb4hSBi6MjcMtfX89dz
+55MBnIMNCSqkW9orrPGKVCGZNpyxIkDqvgiwnm4vIURoHkujhX1UUCcf0Q+EMclY
+EFdEaR/DV72n2uBT7xETbOJEngsN+cgy5t6Bew==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c3.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c3.crt
new file mode 100644
index 00000000000..14582bd47bb
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c3.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUPGx8GdQgamiFY9WkFeBWsOMKRGUwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjguYzMwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuOC5jMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAujTN5UqfbXzpFTjLfl3XOWsQEHD+d5VJIkwTcA6PxUL9CCJCapgylbJQ+nzd
+pfOaUPZkSV75pLxfuimDz0Y8KtlVzEry0zhTgdMSos/ZVdQCn8j79W2/19HVBAMH
+Rd+RDH6oNR3BPNLiW/hycXOyZUOBUtHQ3OMP7d+7dsqGMNkCAwEAAaN/MH0wHQYD
+VR0OBBYEFFoGk7U4lpbzmRjPIEvIsZFoTYd7MB8GA1UdIwQYMBaAFFoGk7U4lpbz
+mRjPIEvIsZFoTYd7MDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0ZXIz
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBsqZfT
+V6gBfsknJp0g4vbZ4ipMOxBQpmEYUUFTUn4vWX1UAhw9tdfFx6p3yLwrPBBeuPT4
+WfL6goaR46aCAELLA9RvcvGGiWysAfPChdHY5ELdDN5ACOyLa9aCY6CMzoMqho+5
+v8F4i6Rg/hFT5Xl6X+DtJrevjyyeECIS7MkVwQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c4.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c4.crt
new file mode 100644
index 00000000000..bad3f9a24f2
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c4.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVALsTUZNLfQ0QhhChFKeFVPkVAJ9rMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW44LmM0MB4XDTE4MDQxOTEzMjIxNFoXDTQ1MDkwNDEz
+MjIxNFowEDEOMAwGA1UEAxMFbjguYzQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAIhWp/YCB3cVIrTK0QP6LC5zBZ8avn9isi/QeLXwxw69k+qhHEOReoybnPgX
+yr2wyXLuL6PwyBMfjINDIEZ+N+4TsbYMsE8HiPNYQyZm1mpBI7ux2FbgCbpuJRfK
+A/Pztz4arlBXcHG/tJKistvF+SSrw21t2bLtVZHXBFR0c0NzAgMBAAGjfzB9MB0G
+A1UdDgQWBBSapaWx6oupzaeRg6DMkAo0HwOYrjAfBgNVHSMEGDAWgBSapaWx6oup
+zaeRg6DMkAo0HwOYrjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlOC5jbHVzdGVy
+NC5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEACX/P
+iZsjozczvsvkMhB8RLFVo29jjrk99GWKjZeYlmN6ntnmuQZNCgaCPaPLMZnEz33s
+tN7i6DkigTkcDfsLnBzFHo9d6tpi5CeE0gCnXvSfFkAT7ZxR3hC8EJOquGPBy2Jh
+A2L/CTwXmbxmEj/qXqMzsjJr2BDgNjATKv6za5s=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c5.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c5.crt
new file mode 100644
index 00000000000..8124b32c7cb
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c5.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUDXZKYe8N8urRIiGxYze5nudE6ZswDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjguYzUwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuOC5jNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAkcBH4VLWVYKTBK6qDEk5PLnxZVyMiQXZHSYKzaOYJONym1lXYkvpXIDcbzwy
+NyFrMbkRu2OX7gJvDJ9RXcZHXmwJMWrYSIYz2wLO56ZJyae/51Hi7Y/3Ov0QpIr8
+Jw0EVt/1UZPhZO3l5tiPp4hWPPFJO3s64gULPTfqcv3vkPECAwEAAaN/MH0wHQYD
+VR0OBBYEFCt7NDuXp23piqYrueIProkyL5uqMB8GA1UdIwQYMBaAFCt7NDuXp23p
+iqYrueIProkyL5uqMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0ZXI1
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQAz0nxM
+esENmZpDl9A5KJascywHWPlNHziEzwV92IWXZTNts8CUixW3VvhPypWMOWOdvo7g
+bI6KQY82WgFT3GN+X5M+qgxLh7R13mRyOW/ncxbc3dpZhKurlW1bPKhchSR57WHr
+1KSKw70C05tqEbMl3CweZ51EwMDq/1IqO5gpuw==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c6.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c6.crt
new file mode 100644
index 00000000000..dc1bd9c514e
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c6.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUBntPQqqFKoP/ZsDltxJ/FYW7x0QwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjguYzYwHhcNMTgwNDE5MTMyMjE0WhcNNDUwOTA0MTMy
+MjE0WjAQMQ4wDAYDVQQDEwVuOC5jNjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAo8BTGj7hNOsuZUJnVaiuK4LzSMpph4N6WPUXUC9Pt5qN6nUyIOhCCMpaXnqf
+Yl4mJM9Tj0NvDwh2Ar5Kp7O/UIStXHxVOxv+WOq4XTLNZPOOgw8pr9i2BDwp92sE
+xydrnRUX/u4hW+/Fssiw3WpBCGiDb0JJerDLDhGMBVEJW8sCAwEAAaN/MH0wHQYD
+VR0OBBYEFDwuoW6Jy/OB9E4Ztw3fXlA4PjrjMB8GA1UdIwQYMBaAFDwuoW6Jy/OB
+9E4Ztw3fXlA4PjrjMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0ZXI2
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQBJ5uWB
+ctpUMiTKasyyio9jZMMsezuZGNnpOb6ZjwSfX2xbyC3KvNS2Dcb5ajlLaNuRLdqd
+dz/IGzI69cl808fUqsFa9rGJBQvyQQBbtNGE4knQ5pdw3cqJEayMfaliViY0CYya
+t3CmJIB1UZ3/zvbMDhrb8RG+/xYvcagCRpchnQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c7.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c7.crt
new file mode 100644
index 00000000000..6bdf74aade9
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c7.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAZKgAwIBAgIVAITsoW3WKpWQHwqyFSUAIXdectrZMA0GCSqGSIb3DQEB
+CwUAMBAxDjAMBgNVBAMTBW44LmM3MB4XDTE4MDQxOTEzMjIxNVoXDTQ1MDkwNDEz
+MjIxNVowEDEOMAwGA1UEAxMFbjguYzcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBALgPqDe2FNs+O8NC9tcUqFEHNaey5ax022GQ5qAiykKoNCFD+YLxDQW8xNPq
+2/nJIaQhzymUi/1KdPs14gDw6HXmSUXO9juLv413PQ3B4aVfsOKG09JmUAxLbcoA
+Q2PrdFichWWaYEtudF4RzAOtMNGbj+n4QL7JkEAxg0Zl+9NlAgMBAAGjfzB9MB0G
+A1UdDgQWBBR2lHOcDOVXtV6xMd2mHu91ksElnjAfBgNVHSMEGDAWgBR2lHOcDOVX
+tV6xMd2mHu91ksElnjAwBgNVHREEKTAnoCUGA1UEA6AeDBxub2RlOC5jbHVzdGVy
+Ny5lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADgYEAC8Ta
+BWlhJWv75fq+NPy5glqnSgfAGCvNpjRYcxFbkxSUTZkFq5mTtu0J+Ckk4fj2IzgP
+lF+NeNxaWmzoCfsYOLKs2+pChor3eaFEckVJThDdkg17rYMa5Ym/T/Ph+hXWoI95
+3xm1ZZbCVJhdaZzFcCnSghji/g4aeXlE6hLwBmk=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c8.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c8.crt
new file mode 100644
index 00000000000..80beac386fc
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/self-signed/n8.c8.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIUWHiDGtjFMmyQe5o/E90cc8TTAJQwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFbjguYzgwHhcNMTgwNDE5MTMyMjE1WhcNNDUwOTA0MTMy
+MjE1WjAQMQ4wDAYDVQQDEwVuOC5jODCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAwvRhMUXpnmopSSajgAAcImV5vnRLUB88duRl/j6oM0Oq4xxPoKg1HfSjTnJu
+Ld3mrMuTQPU67KodJoZ1keFoeKQGH1S6pDT+GBI+8IcZMZRJXyeourDB5AklqRVK
+PiciepoVCHuePYZKVlsUnWbH1Vg9yMcYW6Jx6zbnS/meIC0CAwEAAaN/MH0wHQYD
+VR0OBBYEFO5ttLIFOaMQELSrMcKok9nD4PqyMB8GA1UdIwQYMBaAFO5ttLIFOaMQ
+ELSrMcKok9nD4PqyMDAGA1UdEQQpMCegJQYDVQQDoB4MHG5vZGU4LmNsdXN0ZXI4
+LmVsYXN0aWNzZWFyY2gwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOBgQCoZw5U
+6LVuXhAIKtncNCTbxfjmeL5JG4GsKb1lS1Xwb5WedO9uAusIXQS2SuLhKvc35EW3
+TJgkDlLfSqtRCx53fwm1cw+HmRRzpmMaiKaJ/K1tdhv7r3bvH+tRVzFHxye2Sai9
+U8gIueP6v/5/T/D6MobHsyXDL9l/flHHdQtsFg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/trusted.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/trusted.crt
new file mode 100644
index 00000000000..b0bc6347f12
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/trusted.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICnzCCAYegAwIBAgIVAIGPp2S8Q7fZEXCgYP6Y1mLt8GfHMA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTE0NTA1NloXDTQ1MDkw
+NDE0NTA1NlowEjEQMA4GA1UEAxMHdHJ1c3RlZDCBnzANBgkqhkiG9w0BAQEFAAOB
+jQAwgYkCgYEAgaYZOZiIelSeQKJCMhMbiS2GLAR5EfdCofzdsHq3yf3VkEf2asL5
+tGfiyb8Ir/CqpQwEo/gWpz3WI3McavBuBGBCCbUutfpbo+cjyJGGxsqDrxCL9Pbw
+3Jg1645NDargrZ9US6C7HCt0fd/L6CSBewMjDEusLiki0yyjWNetVIkCAwEAAaNv
+MG0wHQYDVR0OBBYEFClN+lD2GrgAPQObTVaq2jrZzvZrMB8GA1UdIwQYMBaAFKtG
+6eplyoCil1KnV/uy+jr7l6hfMCAGA1UdEQQZMBegFQYDVQQDoA4MDG5vZGUudHJ1
+c3RlZDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAgJ+wY71LI2qwVnA9H
+3WRdgnpDtgQ8+yuuXJKfsuURIwwe0FeCqiRBe1V9JNeDGl9Ma2Ta1b1Bn5LhKFbO
+ucUMkxwnScY1WNSwOi4njy7KWna9nDjBHyDLBhKsX8gTZbL1wL6a7ENkP/Ukadjm
+Bx+1x0mk0yDGu7bk7MgLXZY9wDAHut4DSHg1kQ1+lhS7SWxgobe8D9c/VRDGJYx0
+dDuIeBlCfXTO7LxAC+WGQ0fw4dkGdQS/i/GeEd8s1LN2Z1AmUD+0Bj1ufRLIGyid
+pCpaS8+c6JOtZypWUGMZb1UWwrQJKBQvNos0XaXjQi3j1o3Q7isYNJC4ttGKpYi+
+KBBG
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/trusted.key b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/trusted.key
new file mode 100644
index 00000000000..eeaabe5d155
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/trusted.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCBphk5mIh6VJ5AokIyExuJLYYsBHkR90Kh/N2werfJ/dWQR/Zq
+wvm0Z+LJvwiv8KqlDASj+BanPdYjcxxq8G4EYEIJtS61+luj5yPIkYbGyoOvEIv0
+9vDcmDXrjk0NquCtn1RLoLscK3R938voJIF7AyMMS6wuKSLTLKNY161UiQIDAQAB
+AoGAE2gbioWMmFMmRSKEqh42Fvibhuc8gDX04W6KeKpF7JR0bV54Qk7hNeH/Dpfr
+4voxcPc1kp3GNk6JSVEnxdIrhYGfaS7EYdWsSGRwXxspc61qYaumHo2K6EaixwgT
+293sNSnUTc/O9Rcj5GlTiFWTC7cQ/TpPDVIBz7B+vBblgqECQQC4mYuRAQGkLVBQ
+jzAe4GKnwgy3Wycq1WMwrfAhdlsTEHQ0a4iUU/ShUdvVdWvK/ZNpM8NR8dB2Gnsw
+ypg3kU6VAkEAs8t+CERxvRmNcyyxncxCqIWjPCAY6O5iqSkomc37qsHKgmjMIHoG
+PSCBO3OeFrnjrxsrqYCMH0z7zir9wF/VJQJBAKxWrPWy+tVLeK+8/i/VTEVR5I1J
+jEdw8CmCOa0D0gL6WYKW4euYdcolohamiPv5wKV2reLS3stj7Z6fhXxbLAECQFYA
+HETwGEePlW1mD3+fWLMrWS1FXSTuAhtQKK+JK7w9/hPq9NkEBT/v8GDzqMbOG+6C
+XJwzdNL0C+5N+hquvFECQBID/Fsey6Yp5sFZNLnLcDRWe88W+rLfYPfC8Q6aV2Tc
+WBAQhu/jpKGtgzw5JdCXc/dzPUg4Cxydva2dOk67UIo=
+-----END RSA PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/untrusted.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/untrusted.crt
new file mode 100644
index 00000000000..6df4b7562bc
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/untrusted.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICoTCCAYmgAwIBAgIVAKSY/rK0x1wPpBB+tziDb1a0nuQ+MA0GCSqGSIb3DQEB
+CwUAMBMxETAPBgNVBAMMCGNlcnRBdXRoMB4XDTE4MDQxOTE0NDk0MFoXDTQ1MDkw
+NDE0NDk0MFowFDESMBAGA1UEAxMJdW50cnVzdGVkMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQCjer2c7PjnEcCmJrXegvt5TbCS4IOnwcUITg28pdbVxYsmU7ii
+Q2YWZ0IOFq6OtnIocbdnw7XcF4968entxz2hrTlUZNrnJFjKEANISfmjLpl9HxnT
+jpLQ0TiNDyzXs1wFcFKzBpnu5KN5SQZHVxsLSrQuCBHs50HADIWUJBZYJQIDAQAB
+o28wbTAdBgNVHQ4EFgQUR2lAwN6w/rq1PCIuj6fSV9n9+b8wHwYDVR0jBBgwFoAU
+q0bp6mXKgKKXUqdX+7L6OvuXqF8wIAYDVR0RBBkwF6AVBgNVBAOgDgwMc29tZW9u
+ZS5lbHNlMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBADk+8mcvS5vSkPOO
+CrMEo66J/00pTEPkfEJiXSHY+ueoDS1TsxV/hc8YBeM2KJLY1eDpci1Sr0Ce/UlG
+r+FOT//yIlsSGjjggI82NdB4vm6jXJUBj5Fqi4DKM+qGgrbx0iTvtKliBC+xxz+J
+13eFJhNtFa5oGmb5JtmUAzXE8oFPLmKLl0CEJIz0xdniN7r5eILvD8+k+NhM/ecK
+6TpC3B98vxY/ILNK+YqKg/U8ySMdcufKSVxNQll2OWkM3fLBrTelm9wqPIgBy6Hm
+7K1t6fvbCVnQAe2MiPPPuUaxoeNPCQethLwVd8VfvYjRDkSKx95vqRD107WOxURG
+SQlignQ=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/untrusted.key b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/untrusted.key
new file mode 100644
index 00000000000..c4ab28fda78
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/untrusted.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQCjer2c7PjnEcCmJrXegvt5TbCS4IOnwcUITg28pdbVxYsmU7ii
+Q2YWZ0IOFq6OtnIocbdnw7XcF4968entxz2hrTlUZNrnJFjKEANISfmjLpl9HxnT
+jpLQ0TiNDyzXs1wFcFKzBpnu5KN5SQZHVxsLSrQuCBHs50HADIWUJBZYJQIDAQAB
+AoGASK24vptbzN7HlxZ+pH327ubrKWFHJr2uqxKIaOYRrNg2FMQDwZ/VMwCVDU5o
+LGpQNkrYDvmjUEXpM+944I1DiHZo/g6m2i0Kq6PQevMkYIof4SaUKfc0weG7Kk2T
+KYhGKOCcoXSvPxBKLno1DNvM/hDnBksjX5y9jgl5zxk/jAECQQDi9hgJiVB4WaTy
+gBCfg99+8fj9cZL6VebmXrAGSp6KREwRdCJTTqcnYU2IlyXo0I0iRmW1+j24N0Qu
+pyAsBxa1AkEAuGVbo6zjrTglIOuuSQrjwIVBcFYlxL//OpZHPOvcaptMgCOSqC6R
+jIks+nao8coN/e2mI+WK6Z5IEhi4H9sxsQJBAId5/r8yiCZO3HckmsedIDvWlJo0
+wVdND5dTzh7zS8+dFQsWF6dCu+R14KI4Fxjx5E0hWHVX+p+L3dc7S6j8UkECQFmY
+Df2qDHnmtMuZF/avjtfFJ3WQtgsyCq4JxJVKOK+nw3TjU+fZsKirIiqUKyRIO6Is
+rTP13RgD6xq33gbEdxECQQCR4FfIp9g78QSPILpFRaGnQJoKuPLNu4Z/H1yi/6K+
+Xni82h3W7iFVUwunOsY8AX1jn2Jdy8JyFC4IFhlbWy4L
+-----END RSA PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key-noparam-pkcs8.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key-noparam-pkcs8.pem
new file mode 100644
index 00000000000..94a04b6294a
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key-noparam-pkcs8.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg3vgTh87U+rz2GHs1
+iNQEW7tqSgcLfpm+Wcd9wIBKrlOhRANCAATDEUzFdR6rWTx+3cLViKv5C8PHGFfL
+yu2zezItPavSUKIG78EZFYq/G9f9w4FBLy7/vLvM4HCHMdomlrWi8635
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/rsa_key_pkcs8_plain.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/rsa_key_pkcs8_plain.pem
new file mode 100644
index 00000000000..dd1675957f6
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/rsa_key_pkcs8_plain.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDesZnVBuxbT4y7
+KtIuYx8MUq0sGQgVbxXSBG66sWDU9Qoo1HUyra0xXCONgRMBT9RjSIpk7OOC9g8q
+ENNgFO179YdHVkrgJhW/tNBf+C0VAb+B79zu7SwtyH2nt9t378dmItL+sERkMiiG
++BS/O+cDz44hifDiS7Eqj/mJugAhLjWSUyD+UBObxXvUsxjryKeG3vX9mRCgAcqB
+xH3PjI1i9DVaoobwMbwpE5eW2WXexOspuXnMmGfrrR6z/VmdHqe/C3rGdJOX+Y0c
+yOR+/Vuzisn+nLeo/GJx2hIif8rKiNRyAdUXfx+4DLYJBN2NUbl9aP2LP6ZC8ubf
+6qwhhB0XAgMBAAECggEBAKuzP6qSNfaJNTayY2/EmRHFRSP1ANiV17sgE8f6L3DC
+pdypQtuaMSkXo4nc9SxTwqvyKFJ8m0ZENZj3dCJmwFyNCIqmLAD7HFW9MdRs40WJ
+HYEv0aaeUyvRo6CHD74/r/w96XTZr0GZssmtyUFRDGNRyoJter7gIW9xprLcKHFr
+YTmdaAXbOm5W/K3844EBouTYzYnZYWQjB3jT/g5dIic3AtLb5YfGlpaXXb74xTOU
+BqY1uKonGiDCh0aXXRl2Ucyre6FWslNNy4cAAXm6/5GT6iMo7wDXQftvtyK2IszP
+IFcOG6xcAaJjgZ5wvM3ch0qNhQi4vL7c4Bm5JS9meoECgYEA88ItaVrfm2osX/6/
+fA8wYxxYU5RQRyOgLuzBXoRkISynLJaLVj2gFOQxVQeUK++xK6R182RQatOJcWFT
+WwmIL3CchCwnnXgPvMc51iFKY94DbdvrRatP8c5sSk7IQlpS3aVa7f7DCqexggr5
+3PYysuiLirL+n9I1oZiUxpsS6/cCgYEA6eCcDshQzb7UQfWy//BRMp7u6DDuq+54
+38kJIFsPX0/CGyWsiFYEac8VH7jaGof99j7Zuebeb50TX57ZCBEK2LaHe474ggkY
+GGSoo3VWBn44A1P5ADaRGRwJ4/u79qAg0ldnyxFHWtW+Wbn11DoOg40rl+DOnFBJ
+W+bWJn4az+ECgYEAzWduDt5lmLfiRs4LG4ZNFudWwq8y6o9ptsEIvRXArnfLM3Z0
+Waq6T4Bu1aD6Sf/EAuul/QAmB67TnbgOnqMsoBU7vuDaTQZT9JbI9Ni+r+Lwbs2n
+tuCCEFgKxp8Wf1tPgriJJA3O2xauLNAE9x57YGk21Ry6FYD0coR5sdYRHscCgYEA
+lGQM4Fw82K5RoqAwOK/T9RheYTha1v/x9ZtqjPr53/GNKQhYVhCtsCzSLFRvHhJX
+EpyCLK/NRmgVWMBC2BloFmSJxd3K00bN4PxM+5mBQZFoHMR04qu8mH/vzpV0h2DG
+Mm9+zZti+MFRi0CwNz2248T4ed8LeKaARS1LhxTQEkECgYBFsPNkfGWyP4zsgzFs
+3tMgXnIgl3Lh+vnEIzVakASf3RZrSucJhA713u5L9YB64wPdVJp4YZIoEmHebP9J
+Jt1f9ghcWk6ffUVBQJPmWuRbB/BU8SI+kgtf50Jnizbfm5qoQEt2UdGUbwU3P1+t
+z4SnBvIZ3b2inN+Hwdm5onOBlw==
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes128.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes128.pem
new file mode 100644
index 00000000000..b4448ec8afa
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes128.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,AD45A956510B909DCCACCE07DE3BA1C2
+
+Vk+KErTbsSdjNO5vaCpik/OLkaOQ4Fm3rNIUrQPMEBiK/TXnHMvC/X1DZenSwA8W
+yHuSpoAAg/HjQv5UskRtn6Rt74ALViM4hO6BleNxr/8lIBZAeLNjqoGwf62MyExV
+rraRhXvYepiTnVSQDYuTafxdIXqzg7O5kYcR46gpphXTjMWDMLxsEiKQ1u51lPFU
+SzxSMGMKiJL3PAXuWyoKgUihw6sv+mVPzq4MVcZKTrlcNRGRFQWUhVzqNd5Qdx/v
+vBUFbWVcMXx4tSsx/WtIOiUwZTbmLk4dpXysb0+Tp6lb+7AQ2RR+9tkBWEdBPUx9
+qkBfFdAvfnA5vKR0SwAZU0dFaDWlQD2ktCJv4hwPN0XYMIv5WW9HoA+R88y+dhHT
+sYgM3eEusQv9byC+XCzxPNg40yC8X9TG2z2deMUl6ippsrTULPx1WaoLf12x1Yl3
+vZ7MFB2hvJmWYofjTVz7Xa3FMH1dhJgBTwpUY//EgPhSaTrEMGwrXJQk40nam/LX
+KjK/acvYmZHZZZJ+E0Pv481tFiiWVlXqfI9Tw1ffi4EzezhQTtzz2EBHaanHNEFa
+C+7XQnxmBoNPpwOBh4Lh9oLcDN9uOGBLb+dIzn2cNQZXhBCKI8IV14YtZGZYhRHg
+D+q7V6I/lEd1WNerHZRNI9o4ZBTJl+7GlJ1gveDTdcx28hCdC5oae6ZwIzSZPuDA
+JPF3vr2yci7JsUpBqnaSnxpz5eKYbng3WjqweBXNgRWLhF8HT8fmWNJyvYjWpg+x
+c8vh/FEM1HY3jsxE8NtIAlObJDMm/K/k8keVbbGm8c58oKdO4kdM+Z6aLe53nFo8
+ISwxsps//eak25Rx2H0bNvO4LVhqNHPXyYQ2nqtx7UpEgndrggHP7n3vcjtdE1f3
+N83gSm6SIVIeQJom16Z5Cjm4PRvJltIf2njpLTeP43eMoYNNVSCr2iZyrSNXnEes
+TI47HidjCNkCp5ahPnuzzyeBCo9L9x2odTNOrga8sBii7VQBE3cGhAFkaUf0E6os
+gpPqUWHkXE9Nb6H6EBR4gwbdpUqcgrm+kp6Ei5N/z7gSfV91WO45WmMLpCPmlPDQ
+An+drt25y+AhaIEmoczUGAiz3jOdyd6Xqw+dVXGb9WPxXL4YnXgr4mSC2am9Vad6
+/MgIqYfqA/AOW1wY2dhoqfAGG2ITadFh82W6cqMhmeDQtDFb6/s96O4e46zev+fP
+Nhro3k+JnL3InC9qAvkxEa/FpbL205X3X3FTXM6xK9ZDvq8+hbPxCjg73mXQfbbG
+0/M8hE5hDgILTPiHhHFzGVNjYTAvjNnttg1n7+A52WGs+Hfwlf2x10p8Y2YwyOon
+qfEMM3G1C3sDzEYmo+w0IZ+pesMWejMPOFiHYRCWVl8r5jx9lTSvbB3Xj+0Ygyo9
+15iLEGyr623I8LDBegqpNntlhX+AeHuJcthPRB6Jl2S0Q1xikD4fW1Ge29/l9Ndi
+7TvZoSGh1jfA71pE1Ay2RyH5PMNj8KJvTGZPFEuIdzDUKlJkC3xUEvl6Q0prU171
+d/ka98AxLR9jUur0ARqxsckd5IXDTlZqsRs8W/gk5FP9RibiN7upiJcKgwYddiJx
+-----END RSA PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes192.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes192.pem
new file mode 100644
index 00000000000..4696e77bd3f
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes192.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,FACBF3734C8DD3C53F31E294D7E8DC16
+
+9g2VpXQljNeeag2/jh0b1aKE+xcbkNKfIMeUljhiOxULegO53Apn/THshhJhtgPG
+VYRlmk1ImCnwbWiy4C7WVXbOh1yGbYMPLipbtjEI7dr7OPbRX+GYn2Sln6iW9K61
+A019xPz1dLJ4bciNf5gcq5Wf/Qxj8R33ZPqANIHyMeZDSdGqFu+BQyQuQtJqFLkv
+nokev80VIRuxinfmV3RSdUHo3g7iXRNq10bwxV+fns5fyzm5eq4q8Ac0M2NbhWds
+wVl2gft73W41nXFqgS17Xo7cuAIdE07EGXVOq7UGKwLvAkgRWhZEt0BJZKB3XQAs
+GfApMSOfIfTIS0YFjmkbGMKfprc8cgqPyDafKLDAGwViTWfM5oO2duium7OjV80g
+eaL6iAImxFzfg3n8hsHg31iisM5p6d9VegXlY7YacdkFR11LN47nXoFU9l9vtKPG
+TSouB4/0Dw4eCxmfbmJiO4pe8jn4pk4XhMszqc0Q+fRkHXeEigQgFsI4SSkuNk7r
+EPSMqPSHpB5SkLyccfvd/wSBv1DvfdMIA5+CUUj3qAT7pm6tvtj0ZnXXnUVexlfp
+9+mPMrP0oJ8fSX5kQksCbw+a4C+1ffCzU4S1CUVKboopHzbU2LG80XvjPqXGj2OL
+++ghD7OjcD7DqWkO81FQPadrHqWMa8gf2rHmuamZh58LIpattu99lIHVHfFJhYlg
+s8EEJQRLa7V4/1Mx9uZGKNmjHNzw/QGW5VqZ3MoVTuXQ3uKmfsXdUTpGRszkJzU1
+zpIOGOMWctWcCmTXpYEhYfiNcPK/WyHntlQJpUgutX/Pho4Q9dP0U1fgsHiKTcRJ
+IAg3/pdCiv48K3Wx8Ib+J09mx4wP0rYnaT6f3LSTV+O8u+D8swjngDJ9vYOnyBQt
+Z5nYrCpQcvaTGhWAQdz9OqAmPwjY7aLn3hbT0Jf3aFxH3uiWJi0UE3ahLhNWiDTU
+PT1VtQ1fSt/ZpJM6KduR1aBFYcEyPIE/MQq9Y2jcYKrIyc4OqkZBwVOFZtRx8cQ7
+tsy1iY3FJjKllp1VdDKRtPs1oKqyX3k446iYryjZs3cDbWV+H5MSwxh7yqw+j5qE
+XfvhaImoDFAEisep+w2i7nu80D5uNhFr9bHC/MnRCVlzO1HfrNNns1Oncey1ebJL
+PSmpYAiArym6m6fIM9EtTtUrkNUmU0LeqfAaDUmGgtufmmExOtH7/pEuOfbCzoO9
+ZX+TMBRMlOGg55Wc+J597AyEg9mqGKqgoPF8Si2qEElOFYVlaZ88YGPaXKLKI2DA
+T7LXYlf+njThf948xsgM41JxE2VG6Ibo3ucHXFEF+QVk+Arrv8jQEGNc1n6cv4Ep
+ICoWwHAWN4gvACBi6V0C8Mb5V9cRL6hkCsVZUyOGOKm580qiakxmUe+xGHuMW7Cs
+208L5Lsgnn4ynRKLT0yfup73XdQzut/Bkws4ECdDSoSH45VNMR7bdjoGsWkCn5n/
+gbU8PWTPYL907KLpwRBx8fvmOgP2lLBj2gmwyJeowRlzc1MLtsUnH/7H2YSQJgbX
+0ZKIRHASwjpnlL4uhp1QMn9Nj9H++MiJ59q7kUmZBJstlbyAw11HkP4cwCIccNO4
+-----END RSA PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes256.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes256.pem
new file mode 100644
index 00000000000..64c765456a1
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-aes256.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,134008CB231A5AD0F27EB8F6FB18A873
+
+aJRdAed/XZ+Rl6/s/TwOw8rj+sw2ficvnKjCVJj5wt0+qD2NumPpkXmK9J0+SP21
+Mzzm8H0pQRWrI78vwfFXUxUmQMAuavB9k8HuvZtj1b4GvfHrT/BBbs5wS0RPbE6N
+xZuvTvr5UMYFsP85lotcooau3CLtkVXz9ucMQv9v1r2dBvq/7owzl3M+AxhS1oU2
+f8qc3Q411RhVQl29tZha9gidfzBvOO2HH8AqjHxWMHw448oo/b+fXVrpezD1LkmP
+0JxP+kJDt1KCiwXj7oRAMaHbHemA2HS713TK+6HammQroF0PCB33Dasy6zaPmP5G
+HiJAHvBiblc+vCT7D1lUQCmbjRmeoSESq/P3l8Jhag+wT8SSm5nGaiX7aYHqc00Q
+17Gw5e8/iWOU+c3DjCH5qXZFxVrpJgSvVBrrnF3y4sQCG41QpPC7X3mWYWLHZ5vX
+GxcI4f1aJ+jECDTvdpE9KL6ncZ05p3A3wr+FqrDPJTb+S1mpD0f6lRhnKILXK83N
++EbRVRTCH5QIx5ZepX28ykuZQa6vHGtnL9WXLX4ZgAIe2abMA5hNs72Hi47LUrss
+lA3gMdydKA/WtoimBLqb9brEy9qFsP/2YatKnyXYkjeCgtTQ5LELWSqnFkzQ51wk
+VPhT8SqXcPIe9rrNmf7xwJvcZ0IS4tEkT+TovFAs1lo86bCx7VKfWfxcWG/FvW1L
+5/1tU4uhpXLOjhOvWOx56zqxt9RORMw3SEh3At4vVHqT2xQAStT1d9QU0/QiM3EE
+pBf9uQjRfzlwXph6Gs8XmQYLjSwHurT8hrkoa4/czhE4v7BTst+q6fB3gtxOgV6z
+GVBsRK0Lz0ldd56UvnzyChUpE8EFE/Kv6P7T8cgTPnTcGchO4hcKyC31doAFn0pU
+LURMC5szvRUEHbPriz9/9qeHBLFMAmGkCfXpwjNoynsKA7/VlAd/44CP82Ljd8Fb
+PdwXjz8JNAL+gg3q8Xz4S+z6ZNXVJ1U9GDxjesp7QRbhl1J/ynsGyqIADUmPKjyk
+8yFihQYBiZdgiYaOBl9F2X0SINUKaANmVO7HJG+WbPs68fcObfFHRWugC7FljY+b
+Az6tNhkKVerCXBEMsZ9XNY05SsyAvcKsWcJbxon9ecIeu7/N8k9eseUL0xQg1oQX
+L6wjgmS2ckpPnKVFPXhujZb45PtYEA2ObGd6fPV+82cSgfFM6sPorAmmFhThBXa+
+nE8o72MPVvdUFas3Fs7YugxeFTh9jO4zp/3XA+fFfpxPQbwWjnjxS87OAB+AF6iy
+Ul/jZP46kDOnyLdMLvSf5Oq8A73bdGa/09ODsoWjrXlyYmfUZPKPGQ5Hbs5cUSvs
+GciJvb3o3OYfSjkn6DVF95f53TiJ9pbGY+zG85f/F3BwbqpRmNYLyxvl4ZzjLs+U
+PN24gC78ROzgvHAhY0Ta6PQw8SN5FEoQGmOQT2otZc+Apu1J1Z85mpxd0dYPh29m
+kWvx13gZSGxCvNttqfqcRQJTOerQ4PRIyMDJG/sou8hDU51X9USAfjs1spuE6X/a
+PIGNpM2TIOaqU/IIFJrGx01vVBhYGvYF8D/q+wwwnjJGYQl7Hscc+JdFmhWE0T2R
+-----END RSA PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-unprotected.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-unprotected.pem
new file mode 100644
index 00000000000..1602461b115
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-unprotected.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEA3rGZ1QbsW0+MuyrSLmMfDFKtLBkIFW8V0gRuurFg1PUKKNR1
+Mq2tMVwjjYETAU/UY0iKZOzjgvYPKhDTYBTte/WHR1ZK4CYVv7TQX/gtFQG/ge/c
+7u0sLch9p7fbd+/HZiLS/rBEZDIohvgUvzvnA8+OIYnw4kuxKo/5iboAIS41klMg
+/lATm8V71LMY68inht71/ZkQoAHKgcR9z4yNYvQ1WqKG8DG8KROXltll3sTrKbl5
+zJhn660es/1ZnR6nvwt6xnSTl/mNHMjkfv1bs4rJ/py3qPxicdoSIn/KyojUcgHV
+F38fuAy2CQTdjVG5fWj9iz+mQvLm3+qsIYQdFwIDAQABAoIBAQCrsz+qkjX2iTU2
+smNvxJkRxUUj9QDYlde7IBPH+i9wwqXcqULbmjEpF6OJ3PUsU8Kr8ihSfJtGRDWY
+93QiZsBcjQiKpiwA+xxVvTHUbONFiR2BL9GmnlMr0aOghw++P6/8Pel02a9BmbLJ
+rclBUQxjUcqCbXq+4CFvcaay3Chxa2E5nWgF2zpuVvyt/OOBAaLk2M2J2WFkIwd4
+0/4OXSInNwLS2+WHxpaWl12++MUzlAamNbiqJxogwodGl10ZdlHMq3uhVrJTTcuH
+AAF5uv+Rk+ojKO8A10H7b7citiLMzyBXDhusXAGiY4GecLzN3IdKjYUIuLy+3OAZ
+uSUvZnqBAoGBAPPCLWla35tqLF/+v3wPMGMcWFOUUEcjoC7swV6EZCEspyyWi1Y9
+oBTkMVUHlCvvsSukdfNkUGrTiXFhU1sJiC9wnIQsJ514D7zHOdYhSmPeA23b60Wr
+T/HObEpOyEJaUt2lWu3+wwqnsYIK+dz2MrLoi4qy/p/SNaGYlMabEuv3AoGBAOng
+nA7IUM2+1EH1sv/wUTKe7ugw7qvueN/JCSBbD19PwhslrIhWBGnPFR+42hqH/fY+
+2bnm3m+dE1+e2QgRCti2h3uO+IIJGBhkqKN1VgZ+OANT+QA2kRkcCeP7u/agINJX
+Z8sRR1rVvlm59dQ6DoONK5fgzpxQSVvm1iZ+Gs/hAoGBAM1nbg7eZZi34kbOCxuG
+TRbnVsKvMuqPabbBCL0VwK53yzN2dFmquk+AbtWg+kn/xALrpf0AJgeu0524Dp6j
+LKAVO77g2k0GU/SWyPTYvq/i8G7Np7bgghBYCsafFn9bT4K4iSQNztsWrizQBPce
+e2BpNtUcuhWA9HKEebHWER7HAoGBAJRkDOBcPNiuUaKgMDiv0/UYXmE4Wtb/8fWb
+aoz6+d/xjSkIWFYQrbAs0ixUbx4SVxKcgiyvzUZoFVjAQtgZaBZkicXdytNGzeD8
+TPuZgUGRaBzEdOKrvJh/786VdIdgxjJvfs2bYvjBUYtAsDc9tuPE+HnfC3imgEUt
+S4cU0BJBAoGARbDzZHxlsj+M7IMxbN7TIF5yIJdy4fr5xCM1WpAEn90Wa0rnCYQO
+9d7uS/WAeuMD3VSaeGGSKBJh3mz/SSbdX/YIXFpOn31FQUCT5lrkWwfwVPEiPpIL
+X+dCZ4s235uaqEBLdlHRlG8FNz9frc+EpwbyGd29opzfh8HZuaJzgZc=
+-----END RSA PRIVATE KEY-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks
index 832a23d2dbf..ebe6146124e 100644
Binary files a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks and b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks differ
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.p12 b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.p12
index 2ac8125b58d..0e6bcaa4f8b 100644
Binary files a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.p12 and b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.p12 differ
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt
new file mode 100644
index 00000000000..f4c9a6a7aac
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB7zCCAZOgAwIBAgIEcmggOzAMBggqhkjOPQQDAgUAMCIxIDAeBgNVBAMTF0Vs
+YXN0aWNzZWFyY2ggVGVzdCBOb2RlMB4XDTE4MDUxNzA5MzYxMFoXDTQ1MTAwMjA5
+MzYxMFowIjEgMB4GA1UEAxMXRWxhc3RpY3NlYXJjaCBUZXN0IE5vZGUwWTATBgcq
+hkjOPQIBBggqhkjOPQMBBwNCAATuZRlXGn/ROcO7yFJJ50b20YvgV3U+FpRx0nx/
+yigWj6xiEMKnWbbUnM0mKF8c3GHGk5g8OXPnbK96uj6tpMB5o4G0MIGxMB0GA1Ud
+DgQWBBRNAGO77mUhG6SQvIXQTbpcFwlf2TCBjwYDVR0RBIGHMIGEgglsb2NhbGhv
+c3SCFWxvY2FsaG9zdC5sb2NhbGRvbWFpboIKbG9jYWxob3N0NIIXbG9jYWxob3N0
+NC5sb2NhbGRvbWFpbjSCCmxvY2FsaG9zdDaCF2xvY2FsaG9zdDYubG9jYWxkb21h
+aW42hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMAwGCCqGSM49BAMCBQADSAAwRQIg
+Z3IvdmY5LFdbxoVSs6pV2tJ5+U833Chu0+ZzPo77IVUCIQDRx1FVitVuzBpqwhSW
++Zprt2RLPllC4s4BCApGDh8i1g==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt
new file mode 100644
index 00000000000..75aeecd0c3b
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID0zCCArugAwIBAgIJAPqdcmPxQKraMA0GCSqGSIb3DQEBCwUAMEgxDDAKBgNV
+BAoTA29yZzEWMBQGA1UECxMNZWxhc3RpY3NlYXJjaDEgMB4GA1UEAxMXRWxhc3Rp
+Y3NlYXJjaCBUZXN0IE5vZGUwHhcNMTgwNDMwMTUzODM1WhcNMjIwNDI5MTUzODM1
+WjBIMQwwCgYDVQQKEwNvcmcxFjAUBgNVBAsTDWVsYXN0aWNzZWFyY2gxIDAeBgNV
+BAMTF0VsYXN0aWNzZWFyY2ggVGVzdCBOb2RlMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA0wNzfQ9K9WIs9Le6pfiEHdCI97zGZRqOREKb+zFoDllXEEWW
+Y5mfXRlTYXbxBiCIV5DDW0yaXlleq62j7/O/6prNUBiYo5sK4Wfj+1UlXLmMikkv
+bShm9XzBAXHK20coLJTKOH8QOnFyuVYUvHPCLsoEhQtCHU4zoGaaPmk8w1JU/bfR
++kWmU+x0Ak4rGuRWvMMqg/bu/W/1LmESO5Jsm2CnIyB/22vB08kFn1pO0IIrPQhr
+dXqPxddzxc7DuAyyMyzsrLi5msugynEwm1CTBNL9cG45ujNhWzd1rqQe1HF94mEw
+RinFe2Ui+vLFpNbh8EesLsy0p18J3QkGQ/0xjQIDAQABo4G/MIG8MAkGA1UdEwQC
+MAAwHQYDVR0OBBYEFLUR8gs3uCNdLIwJlkp7SwngpjfhMIGPBgNVHREEgYcwgYSC
+CWxvY2FsaG9zdIIVbG9jYWxob3N0LmxvY2FsZG9tYWluggpsb2NhbGhvc3Q0ghds
+b2NhbGhvc3Q0LmxvY2FsZG9tYWluNIIKbG9jYWxob3N0NoIXbG9jYWxob3N0Ni5s
+b2NhbGRvbWFpbjaHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQEL
+BQADggEBAB73kmak89jgW1q3wIUMfxisokCsk7XuYqPBpc8D06UZBaArCvW2cuLP
+5PLI2bR7fSIhgZmlbawa3adOLZ9n9lOJrWUHTh43kKyiSX8EobE0T/MSGVMfTEFu
+c92erLS2gSDk4wLahzm5htd1h1KwzJ5j5kdzlLGaQsnxDDjbu9BiX/otEyCl8n69
+AZKOXoYscl2NxBgr2V6C2frthJFfQ9Gxzg5q6V/P3aIUyV0xsC3Ve1wdfXqNeRfO
+nrnFbKRDsxJAJ/JtO3GTtqBrFjods0sepKNxFg13r/QLJnYjYW6t7o91JZj2AFOs
+1INZnCOAMV3vR/FOwwOT86HDgrwSy2o=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.jks b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.jks
new file mode 100644
index 00000000000..5a5596dae48
Binary files /dev/null and b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.jks differ
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.p12 b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.p12
new file mode 100644
index 00000000000..b2efbc49899
Binary files /dev/null and b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.p12 differ
diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.pem
new file mode 100644
index 00000000000..131f25a36e1
--- /dev/null
+++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA0wNzfQ9K9WIs9Le6pfiEHdCI97zGZRqOREKb+zFoDllXEEWW
+Y5mfXRlTYXbxBiCIV5DDW0yaXlleq62j7/O/6prNUBiYo5sK4Wfj+1UlXLmMikkv
+bShm9XzBAXHK20coLJTKOH8QOnFyuVYUvHPCLsoEhQtCHU4zoGaaPmk8w1JU/bfR
++kWmU+x0Ak4rGuRWvMMqg/bu/W/1LmESO5Jsm2CnIyB/22vB08kFn1pO0IIrPQhr
+dXqPxddzxc7DuAyyMyzsrLi5msugynEwm1CTBNL9cG45ujNhWzd1rqQe1HF94mEw
+RinFe2Ui+vLFpNbh8EesLsy0p18J3QkGQ/0xjQIDAQABAoIBAG4zFTMws2LnPLco
+5I8c9FJlv8IxkiLm9Xlsl+1dZgxoV/Glhd7KMdH7EfKKnWEnyEyCy6N4o/22Cpz5
+9+2ujIHHCoZT8hMvO0Vwbj2pv/Nm66Cki+IkAXEfD+TjOp+9z5tIsTtEEIOVD+b+
+r6GjirvIwQeCU6reVlPkgZUqfJM8Drh2vOKzTqalJ7Ud4lsHeOaCvAaLp5RKz6sl
+BSX1m3UyRkrOQRFNeD8FwXGgPmxZCbCdLka8em9b2IHFZmfFm+R63NeOWx4wQIF8
+Wh2ncLf3enQU9Xsti1bQ3Q1SALG5Xjf0rtjlk5LklnQ17MuFKLgsIbJ5e9Lg82Bd
+DyrwuMECgYEA+orKql23N9x6J2GdpUHIcJ465b8o8DK/HPE880pwkMKzxaKSMhuP
+VmOi9lJl0QzxL+cqIKoDxQxr9rzY8/fRa+FHPn2ypJeV7osyDCZKcwJyh8PfHD69
+XIhBXlcr9qLLXj1EqKEMGnCAcbDTiLPsReYfpJ4elrtE9gNstIqqOrkCgYEA15w3
+5Y4aqmjCABQW3SyVah772xYJWmscwxJWTrMuBm4EUoMjx2M2qHf8xLPoay4Q9YTR
+v+HtaTw1LAC7tTvuPIGB3Iopj4pyhBWX4m0kxicV7clJFB3eDrl4Dy/70IEJtWxk
+xxdEjxwgFhChWOeB4IdcLc/QnGqIZq9v1WGps3UCgYEA2jU9dAoxRAbToS8EtWTI
+5UT6eRT329Pm3ZdCBYdE6N+a4TvJZrjYK16WFUEIin1iJt2HtHE+3UUHVxt9PWcO
+T44ilcu2ZmHb5Kn5Cdnjp61vAM3YqOn/1PKbNEZp9OIui8KC5Pd26iQnyl0+r2Y9
+F1fpIV/RtmgeFMJA0DGhN4kCgYB5jvzAsmZ8TwWZb7oYRmuS4hcSxRDO5nbX0D3S
+rxiyzVIohwEkB96oCsX6zIer7dPn6FMtQJ5OZ4B+54bsvfYqLMXfZhHaeK7poxb3
+tJs4EI8/ee12pwQr/wseXOo2+plTrOIAkTC5Ep1Qc13UNum1gftJZNHzbeirJBwE
+DMTVhQKBgQCN7jA7Y7eyXdm6fQpCn/gOkKb4dGhKPlrNOrRoD2S/L1YBJjreGZPm
+NARLPO0H1Wrkg54KSIvf69COjVJeyw8L0HGE2eQQOwS7dAvy8rdj+UvABXgaQCxv
+wJsTOZEycAeCyp4wJOLeksMB58bzIXPDOPNlN6buWBVLjm33q7g3Rg==
+-----END RSA PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordTool.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordTool.java
index 9675453186e..336acbdb181 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordTool.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordTool.java
@@ -8,9 +8,7 @@ package org.elasticsearch.xpack.security.authc.esnative.tool;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
-import org.bouncycastle.util.io.Streams;
import org.elasticsearch.ExceptionsHelper;
-import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.EnvironmentAwareCommand;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.LoggingAwareMultiCommand;
@@ -37,6 +35,7 @@ import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
import org.elasticsearch.xpack.security.authc.esnative.tool.HttpResponse.HttpResponseBuilder;
import javax.net.ssl.SSLException;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
@@ -45,7 +44,6 @@ import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -531,7 +529,7 @@ public class SetupPasswordTool extends LoggingAwareMultiCommand {
private HttpResponseBuilder responseBuilder(InputStream is, Terminal terminal) throws IOException {
HttpResponseBuilder httpResponseBuilder = new HttpResponseBuilder();
if (is != null) {
- byte[] bytes = Streams.readAll(is);
+ byte[] bytes = toByteArray(is);
String responseBody = new String(bytes, StandardCharsets.UTF_8);
terminal.println(Verbosity.VERBOSE, responseBody);
httpResponseBuilder.withResponseBody(responseBody);
@@ -545,7 +543,7 @@ public class SetupPasswordTool extends LoggingAwareMultiCommand {
return new URL(url, (url.toURI().getPath() + path).replaceAll("/+", "/") + query);
}
}
-
+
private String getErrorCause(HttpResponse httpResponse) {
final Object error = httpResponse.getResponseBody().get("error");
if (error == null) {
@@ -572,6 +570,17 @@ public class SetupPasswordTool extends LoggingAwareMultiCommand {
return error.toString();
}
+ private byte[] toByteArray(InputStream is) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] internalBuffer = new byte[1024];
+ int read = is.read(internalBuffer);
+ while (read != -1) {
+ baos.write(internalBuffer, 0, read);
+ read = is.read(internalBuffer);
+ }
+ return baos.toByteArray();
+ }
+
/**
* This class is used to capture x-pack security feature configuration.
*/
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java
index a956351f86e..e65ac29aafe 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java
@@ -27,7 +27,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmConfig;
import org.elasticsearch.xpack.core.security.authc.RealmSettings;
import org.elasticsearch.xpack.core.security.authc.pki.PkiRealmSettings;
import org.elasticsearch.xpack.core.security.user.User;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings;
import org.elasticsearch.xpack.security.authc.BytesKey;
import org.elasticsearch.xpack.security.authc.support.CachingRealm;
@@ -216,7 +216,8 @@ public class PkiRealm extends Realm implements CachingRealm {
String trustStoreType = SSLConfigurationSettings.getKeyStoreType(PkiRealmSettings.SSL_SETTINGS.truststoreType,
settings, truststorePath);
try {
- return CertUtils.trustManager(truststorePath, trustStoreType, password.getChars(), trustStoreAlgorithm, realmConfig.env());
+ return CertParsingUtils.trustManager(truststorePath, trustStoreType, password.getChars(), trustStoreAlgorithm, realmConfig
+ .env());
} catch (Exception e) {
throw new IllegalArgumentException("failed to load specified truststore", e);
}
@@ -227,8 +228,8 @@ public class PkiRealm extends Realm implements CachingRealm {
List certificateAuthorities = settings.getAsList(PkiRealmSettings.SSL_SETTINGS.caPaths.getKey(), null);
assert certificateAuthorities != null;
try {
- Certificate[] certificates = CertUtils.readCertificates(certificateAuthorities, env);
- return CertUtils.trustManager(certificates);
+ Certificate[] certificates = CertParsingUtils.readCertificates(certificateAuthorities, env);
+ return CertParsingUtils.trustManager(certificates);
} catch (Exception e) {
throw new ElasticsearchException("failed to load certificate authorities for PKI realm", e);
}
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlMetadataCommand.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlMetadataCommand.java
index ce63a7bd548..9aad0272f48 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlMetadataCommand.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlMetadataCommand.java
@@ -7,16 +7,13 @@ package org.elasticsearch.xpack.security.authc.saml;
import java.io.IOException;
import java.io.InputStream;
-import java.io.Reader;
import java.io.Writer;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.Key;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
@@ -51,7 +48,8 @@ import org.elasticsearch.env.Environment;
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
import org.elasticsearch.xpack.core.security.authc.RealmSettings;
import org.elasticsearch.xpack.core.security.authc.saml.SamlRealmSettings;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
+import org.elasticsearch.xpack.core.ssl.PemUtils;
import org.elasticsearch.xpack.security.authc.saml.SamlSpMetadataBuilder.ContactInfo;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.core.xml.io.MarshallingException;
@@ -67,7 +65,6 @@ import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import static org.elasticsearch.xpack.core.security.authc.RealmSettings.getRealmType;
-import static org.elasticsearch.xpack.security.authc.saml.SamlRealm.require;
/**
* CLI tool to generate SAML Metadata for a Service Provider (realm)
@@ -289,7 +286,7 @@ public class SamlMetadataCommand extends EnvironmentAwareCommand {
if (options.has(signingPkcs12PathSpec)) {
Path p12Path = resolvePath(signingPkcs12PathSpec.value(options));
Map keys = withPassword("certificate bundle (" + p12Path + ")", password,
- terminal, keyPassword -> CertUtils.readPkcs12KeyPairs(p12Path, keyPassword, a -> keyPassword, env));
+ terminal, keyPassword -> CertParsingUtils.readPkcs12KeyPairs(p12Path, keyPassword, a -> keyPassword));
if (keys.size() != 1) {
throw new IllegalArgumentException("expected a single key in file [" + p12Path.toAbsolutePath() + "] but found [" +
@@ -302,7 +299,7 @@ public class SamlMetadataCommand extends EnvironmentAwareCommand {
Path cert = resolvePath(signingCertPathSpec.value(options));
Path key = resolvePath(signingKeyPathSpec.value(options));
final String resolvedSigningCertPath = cert.toAbsolutePath().toString();
- Certificate[] certificates = CertUtils.readCertificates(Collections.singletonList(resolvedSigningCertPath), env);
+ Certificate[] certificates = CertParsingUtils.readCertificates(Collections.singletonList(resolvedSigningCertPath), env);
if (certificates.length != 1) {
throw new IllegalArgumentException("expected a single certificate in file [" + resolvedSigningCertPath + "] but found [" +
certificates.length + "]");
@@ -334,8 +331,8 @@ public class SamlMetadataCommand extends EnvironmentAwareCommand {
private static PrivateKey readSigningKey(Path path, char[] password, Terminal terminal)
throws Exception {
AtomicReference passwordReference = new AtomicReference<>(password);
- try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
- return CertUtils.readPrivateKey(reader, () -> {
+ try {
+ return PemUtils.readPrivateKey(path, () -> {
if (password != null) {
return password;
}
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlRealm.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlRealm.java
index d7d231af680..765d1dc8ad8 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlRealm.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlRealm.java
@@ -44,7 +44,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmConfig;
import org.elasticsearch.xpack.core.security.authc.RealmSettings;
import org.elasticsearch.xpack.core.security.authc.saml.SamlRealmSettings;
import org.elasticsearch.xpack.core.security.user.User;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
import org.elasticsearch.xpack.core.ssl.SSLService;
import org.elasticsearch.xpack.core.ssl.X509KeyPairSettings;
import org.elasticsearch.xpack.security.authc.Realms;
@@ -301,7 +301,8 @@ public final class SamlRealm extends Realm implements Releasable {
private static List buildCredential(RealmConfig config, X509KeyPairSettings keyPairSettings,
Setting aliasSetting, final boolean allowMultiple) {
- final X509KeyManager keyManager = CertUtils.getKeyManager(keyPairSettings, config.settings(), null, config.env());
+ final X509KeyManager keyManager = CertParsingUtils.getKeyManager(keyPairSettings, config.settings(), null, config.env());
+
if (keyManager == null) {
return null;
}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClientTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClientTests.java
index d127a45d532..0d689adcdf5 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClientTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClientTests.java
@@ -5,8 +5,6 @@
*/
package org.elasticsearch.xpack.security.authc.esnative.tool;
-import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.util.io.Streams;
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
@@ -22,17 +20,12 @@ import org.elasticsearch.xpack.security.authc.esnative.tool.HttpResponse.HttpRes
import org.junit.After;
import org.junit.Before;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-
-import javax.security.auth.DestroyFailedException;
/**
* This class tests {@link CommandLineHttpClient} For extensive tests related to
@@ -73,15 +66,14 @@ public class CommandLineHttpClientTests extends ESTestCase {
}
CommandLineHttpClient client = new CommandLineHttpClient(settings, environment);
HttpResponse httpResponse = client.execute("GET", new URL("https://localhost:" + webServer.getPort() + "/test"), "u1",
- new SecureString(new char[] { 'p' }), () -> null, is -> responseBuilder(is));
+ new SecureString(new char[]{'p'}), () -> null, is -> responseBuilder(is));
assertNotNull("Should have http response", httpResponse);
assertEquals("Http status code does not match", 200, httpResponse.getHttpStatus());
assertEquals("Http response body does not match", "complete", httpResponse.getResponseBody().get("test"));
}
- private MockWebServer createMockWebServer() throws IOException, UnrecoverableKeyException, CertificateException,
- NoSuchAlgorithmException, KeyStoreException, OperatorCreationException, DestroyFailedException {
+ private MockWebServer createMockWebServer() {
Path resource = getDataPath("/org/elasticsearch/xpack/security/keystore/testnode.jks");
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
@@ -94,9 +86,20 @@ public class CommandLineHttpClientTests extends ESTestCase {
private HttpResponseBuilder responseBuilder(final InputStream is) throws IOException {
final HttpResponseBuilder httpResponseBuilder = new HttpResponseBuilder();
if (is != null) {
- byte[] bytes = Streams.readAll(is);
+ byte[] bytes = toByteArray(is);
httpResponseBuilder.withResponseBody(new String(bytes, StandardCharsets.UTF_8));
}
return httpResponseBuilder;
}
+
+ private byte[] toByteArray(InputStream is) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] internalBuffer = new byte[1024];
+ int read = is.read(internalBuffer);
+ while (read != -1) {
+ baos.write(internalBuffer, 0, read);
+ read = is.read(internalBuffer);
+ }
+ return baos.toByteArray();
+ }
}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticatorTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticatorTests.java
index 477bfdebb59..3b6c9bf7401 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticatorTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticatorTests.java
@@ -153,9 +153,9 @@ public class SamlAuthenticatorTests extends SamlTestCase {
*/
@BeforeClass
public static void initCredentials() throws Exception {
- idpSigningCertificatePair = createKeyPair(randomSigningAlgorithm());
- spSigningCertificatePair = createKeyPair(randomSigningAlgorithm());
- spEncryptionCertificatePairs = Arrays.asList(createKeyPair("RSA"), createKeyPair("RSA"));
+ idpSigningCertificatePair = readRandomKeyPair(randomSigningAlgorithm());
+ spSigningCertificatePair = readRandomKeyPair(randomSigningAlgorithm());
+ spEncryptionCertificatePairs = Arrays.asList(readKeyPair("RSA_2048"), readKeyPair("RSA_4096"));
}
private static String randomSigningAlgorithm() {
@@ -374,7 +374,7 @@ public class SamlAuthenticatorTests extends SamlTestCase {
final String xml = getSimpleResponse(now);
// Encrypting with different cert instead of sp cert will mean that the SP cannot decrypt
- final String encrypted = encryptAssertions(xml, createKeyPair("RSA"));
+ final String encrypted = encryptAssertions(xml, readKeyPair("RSA_1024"));
assertThat(encrypted, not(equalTo(xml)));
final String signed = signDoc(encrypted);
@@ -391,7 +391,7 @@ public class SamlAuthenticatorTests extends SamlTestCase {
final String xml = getSimpleResponse(now);
// Encrypting with different cert instead of sp cert will mean that the SP cannot decrypt
- final String encrypted = encryptAttributes(xml, createKeyPair("RSA"));
+ final String encrypted = encryptAttributes(xml, readKeyPair("RSA_4096_updated"));
assertThat(encrypted, not(equalTo(xml)));
final String signed = signDoc(encrypted);
@@ -937,7 +937,7 @@ public class SamlAuthenticatorTests extends SamlTestCase {
assertThat(authenticator.authenticate(token(signer.transform(xml, idpSigningCertificatePair))), notNullValue());
// check is rejected when signed by a different key-pair
- final Tuple wrongKey = createKeyPair(randomSigningAlgorithm());
+ final Tuple wrongKey = readRandomKeyPair(randomSigningAlgorithm());
final ElasticsearchSecurityException exception = expectThrows(ElasticsearchSecurityException.class,
() -> authenticator.authenticate(token(signer.transform(xml, wrongKey))));
assertThat(exception.getMessage(), containsString("SAML Signature"));
@@ -953,7 +953,8 @@ public class SamlAuthenticatorTests extends SamlTestCase {
assertThat(authenticator.authenticate(token(signer.transform(xml, idpSigningCertificatePair))), notNullValue());
final Tuple oldKeyPair = idpSigningCertificatePair;
- idpSigningCertificatePair = createKeyPair(randomSigningAlgorithm());
+ //Ensure we won't read any of the ones we could have picked randomly before
+ idpSigningCertificatePair = readKeyPair("RSA_4096_updated");
assertThat(idpSigningCertificatePair.v2(), not(equalTo(oldKeyPair.v2())));
assertThat(authenticator.authenticate(token(signer.transform(xml, idpSigningCertificatePair))), notNullValue());
}
@@ -1013,7 +1014,7 @@ public class SamlAuthenticatorTests extends SamlTestCase {
final List> keys = new ArrayList<>(numberOfKeys);
final List credentials = new ArrayList<>(numberOfKeys);
for (int i = 0; i < numberOfKeys; i++) {
- final Tuple key = createKeyPair(randomSigningAlgorithm());
+ final Tuple key = readRandomKeyPair(randomSigningAlgorithm());
keys.add(key);
credentials.addAll(buildOpenSamlCredential(key));
}
@@ -1941,4 +1942,4 @@ public class SamlAuthenticatorTests extends SamlTestCase {
return new SamlToken(content, singletonList(requestId));
}
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlLogoutRequestHandlerTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlLogoutRequestHandlerTests.java
index 06d0ce4a179..d88ad14def6 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlLogoutRequestHandlerTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlLogoutRequestHandlerTests.java
@@ -48,7 +48,7 @@ public class SamlLogoutRequestHandlerTests extends SamlTestCase {
@BeforeClass
public static void setupCredential() throws Exception {
- credential = (X509Credential)buildOpenSamlCredential(createKeyPair()).get(0);
+ credential = (X509Credential) buildOpenSamlCredential(readRandomKeyPair()).get(0);
}
@AfterClass
@@ -210,7 +210,7 @@ public class SamlLogoutRequestHandlerTests extends SamlTestCase {
final Settings realmSettings = Settings.EMPTY;
final IdpConfiguration idp = new IdpConfiguration(IDP_ENTITY_ID, () -> Collections.singletonList(credential));
- final X509Credential spCredential = (X509Credential)buildOpenSamlCredential(createKeyPair()).get(0);
+ final X509Credential spCredential = (X509Credential) buildOpenSamlCredential(readRandomKeyPair()).get(0);
final SigningConfiguration signingConfiguration = new SigningConfiguration(Collections.singleton("*"), spCredential);
final SpConfiguration sp = new SpConfiguration("https://sp.test/", "https://sp.test/saml/asc", LOGOUT_URL,
signingConfiguration, Arrays.asList(spCredential));
@@ -224,4 +224,4 @@ public class SamlLogoutRequestHandlerTests extends SamlTestCase {
);
}
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlMetadataCommandTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlMetadataCommandTests.java
index 3fdf01bf135..cf41673b86b 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlMetadataCommandTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlMetadataCommandTests.java
@@ -17,7 +17,8 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.TestEnvironment;
import org.elasticsearch.xpack.core.security.authc.RealmSettings;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
+import org.elasticsearch.xpack.core.ssl.PemUtils;
import org.junit.Before;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
@@ -35,7 +36,6 @@ import org.opensaml.xmlsec.signature.support.SignatureValidator;
import org.w3c.dom.Element;
import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyStore;
@@ -143,7 +143,7 @@ public class SamlMetadataCommandTests extends SamlTestCase {
// Verify that OpenSAML things the XML representation is the same as our input
final java.security.cert.X509Certificate javaCert = KeyInfoSupport.getCertificate(xmlCert);
- assertThat(CertUtils.readCertificates(Collections.singletonList(certPath)), arrayContaining(javaCert));
+ assertThat(CertParsingUtils.readCertificates(Collections.singletonList(certPath)), arrayContaining(javaCert));
} else {
assertThat(spDescriptor.getKeyDescriptors(), iterableWithSize(0));
}
@@ -384,7 +384,6 @@ public class SamlMetadataCommandTests extends SamlTestCase {
final EntityDescriptor descriptor = command.buildEntityDescriptor(terminal, options, env);
Element e = command.possiblySignDescriptor(terminal, options, descriptor, env);
- String a = SamlUtils.toString(e);
assertThat(descriptor, notNullValue());
// Verify generated signature
assertThat(descriptor.getSignature(), notNullValue());
@@ -550,8 +549,8 @@ public class SamlMetadataCommandTests extends SamlTestCase {
final Path dir = createTempDir();
final Path ksEncryptionFile = dir.resolve("saml-encryption.p12");
- final Tuple certEncKeyPair1 = createKeyPair("RSA");
- final Tuple certEncKeyPair2 = createKeyPair("RSA");
+ final Tuple certEncKeyPair1 = readKeyPair("RSA_2048");
+ final Tuple certEncKeyPair2 = readKeyPair("RSA_4096");
final KeyStore ksEncrypt = KeyStore.getInstance("PKCS12");
ksEncrypt.load(null);
ksEncrypt.setKeyEntry(getAliasName(certEncKeyPair1), certEncKeyPair1.v2(), "key-password".toCharArray(),
@@ -563,7 +562,7 @@ public class SamlMetadataCommandTests extends SamlTestCase {
}
final Path ksSigningFile = dir.resolve("saml-signing.p12");
- final Tuple certKeyPairSign = createKeyPair("RSA");
+ final Tuple certKeyPairSign = readRandomKeyPair("RSA");
final KeyStore ksSign = KeyStore.getInstance("PKCS12");
ksSign.load(null);
ksSign.setKeyEntry(getAliasName(certKeyPairSign), certKeyPairSign.v2(), "key-password".toCharArray(),
@@ -678,13 +677,16 @@ public class SamlMetadataCommandTests extends SamlTestCase {
}
private String getAliasName(final Tuple certKeyPair) {
- return certKeyPair.v1().getSubjectX500Principal().getName().toLowerCase(Locale.US) + "-alias";
+ // Keys are pre-generated with the same name, so add the serial no to the alias so that keystore entries won't be overwritten
+ return certKeyPair.v1().getSubjectX500Principal().getName().toLowerCase(Locale.US) + "-"+
+ certKeyPair.v1().getSerialNumber()+"-alias";
}
private boolean validateSignature(Signature signature) {
try {
- Certificate[] certificates = CertUtils.readCertificates(Collections.singletonList(getDataPath("saml.crt").toString()), null);
- PrivateKey key = CertUtils.readPrivateKey(Files.newBufferedReader(getDataPath("saml.key"), StandardCharsets.UTF_8),
+ Certificate[] certificates = CertParsingUtils.
+ readCertificates(Collections.singletonList(getDataPath("saml.crt").toString()), null);
+ PrivateKey key = PemUtils.readPrivateKey(getDataPath("saml.key"),
""::toCharArray);
Credential verificationCredential = new BasicX509Credential((java.security.cert.X509Certificate) certificates[0], key);
SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
@@ -695,4 +697,4 @@ public class SamlMetadataCommandTests extends SamlTestCase {
return false;
}
}
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java
index fdcf720bf26..f831af9ba5e 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java
@@ -5,7 +5,6 @@
*/
package org.elasticsearch.xpack.security.authc.saml;
-import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.common.collect.Tuple;
@@ -22,7 +21,8 @@ import org.elasticsearch.xpack.core.security.authc.AuthenticationResult;
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
import org.elasticsearch.xpack.core.security.authc.RealmSettings;
import org.elasticsearch.xpack.core.security.authc.saml.SamlRealmSettings;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
+import org.elasticsearch.xpack.core.ssl.PemUtils;
import org.elasticsearch.xpack.core.ssl.SSLService;
import org.elasticsearch.xpack.core.ssl.TestsSSLService;
import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
@@ -40,17 +40,11 @@ import org.opensaml.saml.saml2.metadata.SingleSignOnService;
import org.opensaml.security.credential.Credential;
import org.opensaml.security.x509.X509Credential;
-import javax.security.auth.x500.X500Principal;
-
-import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
import java.security.KeyStore;
-import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PrivilegedActionException;
import java.security.PublicKey;
@@ -308,17 +302,23 @@ public class SamlRealmTests extends SamlTestCase {
public void testCreateCredentialFromPemFiles() throws Exception {
final Settings.Builder builder = buildSettings("http://example.com");
final Path dir = createTempDir("encryption");
- final KeyPair pair = buildKeyPair();
- final X509Certificate cert = buildCertificate(pair);
- builder.put(REALM_SETTINGS_PREFIX + ".encryption.key", writePemObject(dir, "enc.key", pair.getPrivate()).toString());
- builder.put(REALM_SETTINGS_PREFIX + ".encryption.certificate", writePemObject(dir, "enc.crt", cert).toString());
+ final Path encryptionKeyPath = getDataPath("encryption.key");
+ final Path destEncryptionKeyPath = dir.resolve("encryption.key");
+ final PrivateKey encryptionKey = PemUtils.readPrivateKey(encryptionKeyPath, "encryption"::toCharArray);
+ final Path encryptionCertPath = getDataPath("encryption.crt");
+ final Path destEncryptionCertPath = dir.resolve("encryption.crt");
+ final X509Certificate encryptionCert = CertParsingUtils.readX509Certificates(Collections.singletonList(encryptionCertPath))[0];
+ Files.copy(encryptionKeyPath, destEncryptionKeyPath);
+ Files.copy(encryptionCertPath, destEncryptionCertPath);
+ builder.put(REALM_SETTINGS_PREFIX + ".encryption.key", destEncryptionKeyPath);
+ builder.put(REALM_SETTINGS_PREFIX + ".encryption.certificate", destEncryptionCertPath);
final Settings settings = builder.build();
final RealmConfig realmConfig = realmConfigFromGlobalSettings(settings);
final Credential credential = SamlRealm.buildEncryptionCredential(realmConfig).get(0);
assertThat(credential, notNullValue());
- assertThat(credential.getPrivateKey(), equalTo(pair.getPrivate()));
- assertThat(credential.getPublicKey(), equalTo(pair.getPublic()));
+ assertThat(credential.getPrivateKey(), equalTo(encryptionKey));
+ assertThat(credential.getPublicKey(), equalTo(encryptionCert.getPublicKey()));
}
public void testCreateEncryptionCredentialFromKeyStore() throws Exception {
@@ -328,9 +328,8 @@ public class SamlRealmTests extends SamlTestCase {
.put("path.home", dir);
final Path ksFile = dir.resolve("cred.p12");
final boolean testMultipleEncryptionKeyPair = randomBoolean();
- final Tuple certKeyPair1 = createKeyPair("RSA");
- final Tuple certKeyPair2 = createKeyPair("RSA");
-
+ final Tuple certKeyPair1 = readKeyPair("RSA_4096");
+ final Tuple certKeyPair2 = readKeyPair("RSA_2048");
final KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null);
ks.setKeyEntry(getAliasName(certKeyPair1), certKeyPair1.v2(), "key-password".toCharArray(),
@@ -374,8 +373,8 @@ public class SamlRealmTests extends SamlTestCase {
final Path dir = createTempDir();
final Settings.Builder builder = Settings.builder().put(REALM_SETTINGS_PREFIX + ".type", "saml").put("path.home", dir);
final Path ksFile = dir.resolve("cred.p12");
- final Tuple certKeyPair1 = createKeyPair("RSA");
- final Tuple certKeyPair2 = createKeyPair("EC");
+ final Tuple certKeyPair1 = readRandomKeyPair("RSA");
+ final Tuple certKeyPair2 = readRandomKeyPair("EC");
final KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null);
@@ -413,9 +412,9 @@ public class SamlRealmTests extends SamlTestCase {
final Path dir = createTempDir();
final Settings.Builder builder = Settings.builder().put(REALM_SETTINGS_PREFIX + ".type", "saml").put("path.home", dir);
final Path ksFile = dir.resolve("cred.p12");
- final Tuple certKeyPair1 = createKeyPair("RSA");
- final Tuple certKeyPair2 = createKeyPair("RSA");
- final Tuple certKeyPair3 = createKeyPair("EC");
+ final Tuple certKeyPair1 = readKeyPair("RSA_4096");
+ final Tuple certKeyPair2 = readKeyPair("RSA_2048");
+ final Tuple certKeyPair3 = readRandomKeyPair("EC");
final KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null);
@@ -501,7 +500,9 @@ public class SamlRealmTests extends SamlTestCase {
}
private String getAliasName(final Tuple certKeyPair) {
- return certKeyPair.v1().getSubjectX500Principal().getName().toLowerCase(Locale.US) + "-alias";
+ // Keys are pre-generated with the same name, so add the serial no to the alias so that keystore entries won't be overwritten
+ return certKeyPair.v1().getSubjectX500Principal().getName().toLowerCase(Locale.US) + "-"+
+ certKeyPair.v1().getSerialNumber()+"-alias";
}
public void testBuildLogoutRequest() throws Exception {
@@ -552,25 +553,6 @@ public class SamlRealmTests extends SamlTestCase {
return descriptor;
}
- private X509Certificate buildCertificate(KeyPair pair) throws Exception {
- return CertUtils.generateSignedCertificate(new X500Principal("CN=idp"), null, pair, null, null, 30);
- }
-
- private KeyPair buildKeyPair() throws NoSuchAlgorithmException {
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
- keyPairGenerator.initialize(2048);
- return keyPairGenerator.generateKeyPair();
- }
-
-
- private Path writePemObject(Path dir, String name, Object object) throws IOException {
- final Path path = dir.resolve(name);
- final JcaPEMWriter writer = new JcaPEMWriter(Files.newBufferedWriter(path, StandardCharsets.US_ASCII));
- writer.writeObject(object);
- writer.close();
- return path;
- }
-
private Tuple buildConfig(String path) throws Exception {
Settings globalSettings = buildSettings(path).build();
final Environment env = TestEnvironment.newEnvironment(globalSettings);
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRedirectTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRedirectTests.java
index d7b2249d14e..434d769a3b7 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRedirectTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRedirectTests.java
@@ -35,7 +35,7 @@ public class SamlRedirectTests extends SamlTestCase {
public void testRedirectUrlWithRelayStateAndSigning() throws Exception {
final SigningConfiguration signing =
- new SigningConfiguration(singleton("*"), (X509Credential) buildOpenSamlCredential(createKeyPair()).get(0));
+ new SigningConfiguration(singleton("*"), (X509Credential) buildOpenSamlCredential(readRandomKeyPair()).get(0));
final SamlRedirect redirect = new SamlRedirect(buildLogoutRequest(LOGOUT_URL), signing);
final String url = redirect.getRedirectUrl("hello");
assertThat(url, startsWith(LOGOUT_URL + "?SAMLRequest=nZFBa4QwFIT%2FSnh3Naa2ax%2FqsiAFYdtDu91DLyVo2AY0cX2x9Oc36gpLC" +
@@ -81,4 +81,4 @@ public class SamlRedirectTests extends SamlTestCase {
return logoutRequest;
}
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlSpMetadataBuilderTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlSpMetadataBuilderTests.java
index 67db2be74f1..1133a71993d 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlSpMetadataBuilderTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlSpMetadataBuilderTests.java
@@ -5,7 +5,7 @@
*/
package org.elasticsearch.xpack.security.authc.saml;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.opensaml.saml.saml2.core.NameID;
@@ -35,7 +35,7 @@ public class SamlSpMetadataBuilderTests extends SamlTestCase {
public void setup() throws Exception {
SamlUtils.initialize(logger);
final Path certPath = getDataPath("saml.crt");
- final Certificate[] certs = CertUtils.readCertificates(Collections.singletonList(certPath));
+ final Certificate[] certs = CertParsingUtils.readCertificates(Collections.singletonList(certPath));
if (certs.length != 1) {
fail("Expected exactly 1 certificate in " + certPath);
}
@@ -46,7 +46,7 @@ public class SamlSpMetadataBuilderTests extends SamlTestCase {
}
final Path threeCertsPath = getDataPath("saml-three-certs.crt");
- final Certificate[] threeCerts = CertUtils.readCertificates(Collections.singletonList(threeCertsPath));
+ final Certificate[] threeCerts = CertParsingUtils.readCertificates(Collections.singletonList(threeCertsPath));
if (threeCerts.length != 3) {
fail("Expected exactly 3 certificate in " + certPath);
}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlTestCase.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlTestCase.java
index 616dfab8fe0..bbd98445295 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlTestCase.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlTestCase.java
@@ -9,28 +9,22 @@ import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.common.collect.Tuple;
+import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.test.ESTestCase;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
+import org.elasticsearch.xpack.core.ssl.PemUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.opensaml.security.credential.Credential;
-import org.opensaml.security.x509.X509Credential;
import org.opensaml.security.x509.impl.X509KeyManagerX509CredentialAdapter;
-import javax.security.auth.x500.X500Principal;
-
-import java.io.IOException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
+import java.nio.file.Path;
import java.security.PrivateKey;
-import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
@@ -68,12 +62,12 @@ public abstract class SamlTestCase extends ESTestCase {
/**
* Generates signed certificate and associates with generated key pair.
- * @see #createKeyPair(String)
+ * @see #readRandomKeyPair(String)
* @return X509Certificate a signed certificate, it's PrivateKey {@link Tuple}
* @throws Exception
*/
- protected static Tuple createKeyPair() throws Exception {
- return createKeyPair("RSA");
+ protected static Tuple readRandomKeyPair() throws Exception {
+ return readRandomKeyPair("RSA");
}
/**
@@ -83,34 +77,45 @@ public abstract class SamlTestCase extends ESTestCase {
* @return X509Certificate a signed certificate, it's PrivateKey {@link Tuple}
* @throws Exception
*/
- protected static Tuple createKeyPair(String algorithm) throws Exception {
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
- final boolean useBigKeySizes = rarely();
+ protected static Tuple readRandomKeyPair(String algorithm) throws Exception {
+ int keySize;
switch (algorithm) {
case "EC":
- keyPairGenerator.initialize(randomFrom(256, 384));
+ keySize = randomFrom(256, 384);
break;
case "RSA":
- keyPairGenerator.initialize(randomFrom(Arrays.stream(new int[] { 1024, 2048, 4096 }).boxed()
- .filter((ksize) -> (ksize <= 2048 || useBigKeySizes)).collect(Collectors.toList())));
+ keySize = randomFrom(1024, 2048, 4096);
break;
case "DSA":
- keyPairGenerator.initialize(randomFrom(Arrays.stream(new int[] { 1024, 2048, 3072 }).boxed()
- .filter((ksize) -> (ksize <= 2048 || useBigKeySizes)).collect(Collectors.toList())));
+ keySize = randomFrom(1024, 2048, 3072);
break;
default:
- keyPairGenerator.initialize(randomFrom(1024, 2048));
+ keySize = randomFrom(1024, 2048);
}
- final KeyPair pair = keyPairGenerator.generateKeyPair();
- final String name = randomAlphaOfLength(8);
- final X509Certificate cert = CertUtils.generateSignedCertificate(new X500Principal("CN=test-" + name), null, pair, null, null, 30);
- return new Tuple<>(cert, pair.getPrivate());
+ Path keyPath = PathUtils.get(SamlTestCase.class.getResource
+ ("/org/elasticsearch/xpack/security/authc/saml/saml_" + algorithm + "_" + keySize + ".key").toURI());
+ Path certPath = PathUtils.get(SamlTestCase.class.getResource
+ ("/org/elasticsearch/xpack/security/authc/saml/saml_" + algorithm + "_" + keySize + ".crt").toURI());
+ X509Certificate certificate = CertParsingUtils.readX509Certificates(Collections.singletonList(certPath))[0];
+ PrivateKey privateKey = PemUtils.readPrivateKey(keyPath, ""::toCharArray);
+ return new Tuple<>(certificate, privateKey);
+ }
+
+ protected static Tuple readKeyPair(String keyName) throws Exception {
+ Path keyPath = PathUtils.get(SamlTestCase.class.getResource
+ ("/org/elasticsearch/xpack/security/authc/saml/saml_" + keyName + ".key").toURI());
+ Path certPath = PathUtils.get(SamlTestCase.class.getResource
+ ("/org/elasticsearch/xpack/security/authc/saml/saml_" + keyName+ ".crt").toURI());
+ X509Certificate certificate = CertParsingUtils.readX509Certificates(Collections.singletonList(certPath))[0];
+ PrivateKey privateKey = PemUtils.readPrivateKey(keyPath, ""::toCharArray);
+ return new Tuple<>(certificate, privateKey);
}
protected static List buildOpenSamlCredential(final Tuple keyPair) {
try {
return Arrays.asList(new X509KeyManagerX509CredentialAdapter(
- CertUtils.keyManager(new Certificate[] { keyPair.v1() }, keyPair.v2(), new char[0]), "key"));
+ CertParsingUtils.keyManager(new Certificate[]{keyPair.v1()}, keyPair.v2(), new char[0]), "key"));
+
} catch (Exception e) {
throw ExceptionsHelper.convertToRuntime(e);
}
@@ -120,7 +125,7 @@ public abstract class SamlTestCase extends ESTestCase {
final List credentials = keyPairs.stream().map((keyPair) -> {
try {
return new X509KeyManagerX509CredentialAdapter(
- CertUtils.keyManager(new Certificate[] { keyPair.v1() }, keyPair.v2(), new char[0]), "key");
+ CertParsingUtils.keyManager(new Certificate[]{keyPair.v1()}, keyPair.v2(), new char[0]), "key");
} catch (Exception e) {
throw ExceptionsHelper.convertToRuntime(e);
}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SigningConfigurationTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SigningConfigurationTests.java
index 01d13601ea0..4784dc1a284 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SigningConfigurationTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SigningConfigurationTests.java
@@ -21,7 +21,7 @@ public class SigningConfigurationTests extends SamlTestCase {
@BeforeClass
public static void setupCredential() throws Exception {
- credential = (X509Credential)buildOpenSamlCredential(createKeyPair()).get(0);
+ credential = (X509Credential) buildOpenSamlCredential(readRandomKeyPair()).get(0);
}
@AfterClass
@@ -62,4 +62,4 @@ public class SigningConfigurationTests extends SamlTestCase {
return new SigningConfiguration(Sets.newHashSet(types), credential);
}
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/DNSOnlyHostnameVerificationTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/DNSOnlyHostnameVerificationTests.java
deleted file mode 100644
index 54e313a9e47..00000000000
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/DNSOnlyHostnameVerificationTests.java
+++ /dev/null
@@ -1,156 +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;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.security.transport.netty4;
-
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.elasticsearch.ElasticsearchException;
-import org.elasticsearch.common.SuppressForbidden;
-import org.elasticsearch.common.network.NetworkAddress;
-import org.elasticsearch.common.network.NetworkService;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.test.SecurityIntegTestCase;
-import org.elasticsearch.test.SecuritySettingsSource;
-import org.elasticsearch.test.SecuritySettingsSourceField;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-import javax.security.auth.x500.X500Principal;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.net.InetAddress;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-/**
- * Tests the use of DNS only certificates with SSL and verifies hostname verification works. The test itself is simple since we just need
- * to check the cluster is formed and green. The setup is a bit more complicated as we do our best to ensure no issues will be encountered
- * with DNS.
- */
-public class DNSOnlyHostnameVerificationTests extends SecurityIntegTestCase {
-
- private static KeyStore keystore = null;
- private static String hostName = null;
-
- @BeforeClass
- public static void resolveNameForMachine() throws Exception {
- assert keystore == null : "keystore is only set by this method and it should only be called once";
- NetworkService networkService = new NetworkService(Collections.emptyList());
- InetAddress inetAddress = networkService.resolvePublishHostAddresses(null);
- hostName = getHostName(inetAddress);
- String hostAddress = NetworkAddress.format(inetAddress);
- assumeFalse("need a local address that can be reverse resolved", hostName.equals(hostAddress));
- // looks good so far, verify forward resolve is ok and proceed
- Optional matchingForwardResolvedAddress = Arrays.stream(InetAddress.getAllByName(hostName))
- .filter((i) -> Arrays.equals(i.getAddress(), inetAddress.getAddress()))
- .findFirst();
- assumeTrue("could not forward resolve hostname: " + hostName, matchingForwardResolvedAddress.isPresent());
- KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
-
- // randomize between CN and SAN
- final X509Certificate cert;
- if (randomBoolean()) {
- cert = CertUtils.generateSignedCertificate(new X500Principal("CN=" + hostName), null, keyPair, null, null, 365);
- } else {
- GeneralName dnsSan = new GeneralName(GeneralName.dNSName, hostName);
- GeneralNames names = new GeneralNames(dnsSan);
- cert = CertUtils.generateSignedCertificate(new X500Principal("CN=esnode"), names, keyPair, null, null, 365);
- }
-
- keystore = KeyStore.getInstance("JKS");
- keystore.load(null, null);
- keystore.setKeyEntry("private key", keyPair.getPrivate(), SecuritySettingsSourceField.TEST_PASSWORD.toCharArray(),
- new Certificate[]{cert});
- }
-
- @AfterClass
- public static void cleanupKeystore() {
- keystore = null;
- hostName = null;
- }
-
- @Override
- public boolean transportSSLEnabled() {
- return true;
- }
-
- @Override
- public Settings nodeSettings(int nodeOrdinal) {
- Settings defaultSettings = super.nodeSettings(nodeOrdinal);
- Settings.Builder builder = Settings.builder()
- .put(defaultSettings.filter((s) -> s.startsWith("xpack.ssl.") == false), false)
- .put("transport.host", hostName);
- Path keystorePath = nodeConfigPath(nodeOrdinal).resolve("keystore.jks");
- try (OutputStream os = Files.newOutputStream(keystorePath)) {
- keystore.store(os, SecuritySettingsSourceField.TEST_PASSWORD.toCharArray());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
- throw new ElasticsearchException("unable to write keystore for node", e);
- }
- SecuritySettingsSource.addSecureSettings(builder, secureSettings -> {
- secureSettings.setString("xpack.ssl.keystore.secure_password", SecuritySettingsSourceField.TEST_PASSWORD);
- secureSettings.setString("xpack.ssl.truststore.secure_password", SecuritySettingsSourceField.TEST_PASSWORD);
- });
- builder.put("xpack.ssl.keystore.path", keystorePath.toAbsolutePath())
- .put("xpack.ssl.truststore.path", keystorePath.toAbsolutePath());
- List unicastHosts = defaultSettings.getAsList("discovery.zen.ping.unicast.hosts").stream()
- .map((s) -> {
- String port = s.substring(s.lastIndexOf(':'), s.length());
- return hostName + port;
- })
- .collect(Collectors.toList());
- builder.putList("discovery.zen.ping.unicast.hosts", unicastHosts);
- return builder.build();
- }
-
- @Override
- public Settings transportClientSettings() {
- Settings defaultSettings = super.transportClientSettings();
- Settings.Builder builder = Settings.builder()
- .put(defaultSettings.filter((s) -> s.startsWith("xpack.ssl.") == false));
- Path path = createTempDir().resolve("keystore.jks");
- try (OutputStream os = Files.newOutputStream(path)) {
- keystore.store(os, SecuritySettingsSourceField.TEST_PASSWORD.toCharArray());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
- throw new ElasticsearchException("unable to write keystore for node", e);
- }
- SecuritySettingsSource.addSecureSettings(builder, secureSettings -> {
- secureSettings.setString("xpack.ssl.keystore.secure_password", SecuritySettingsSourceField.TEST_PASSWORD);
- secureSettings.setString("xpack.ssl.truststore.secure_password", SecuritySettingsSourceField.TEST_PASSWORD);
- });
- builder.put("xpack.ssl.keystore.path", path.toAbsolutePath())
- .put("xpack.ssl.truststore.path", path.toAbsolutePath());
- return builder.build();
- }
-
- public void testThatClusterIsFormed() {
- ensureGreen();
- }
-
- @SuppressForbidden(reason = "need to get the hostname to set as host in test")
- private static String getHostName(InetAddress inetAddress) {
- return inetAddress.getHostName();
- }
-}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java
index 2fa376ec854..e12b2186b4d 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java
@@ -10,7 +10,8 @@ import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.test.SecurityIntegTestCase;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
+import org.elasticsearch.xpack.core.ssl.PemUtils;
import org.junit.BeforeClass;
import javax.net.ssl.HandshakeCompletedEvent;
@@ -73,12 +74,9 @@ public class EllipticCurveSSLTests extends SecurityIntegTestCase {
public void testConnection() throws Exception {
final Path keyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key.pem");
final Path certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-cert.pem");
- PrivateKey privateKey;
- try (Reader reader = Files.newBufferedReader(keyPath)) {
- privateKey = CertUtils.readPrivateKey(reader, () -> null);
- }
- Certificate[] certs = CertUtils.readCertificates(Collections.singletonList(certPath.toString()), null);
- X509ExtendedKeyManager x509ExtendedKeyManager = CertUtils.keyManager(certs, privateKey, new char[0]);
+ PrivateKey privateKey = PemUtils.readPrivateKey(keyPath, () -> null);
+ Certificate[] certs = CertParsingUtils.readCertificates(Collections.singletonList(certPath.toString()), null);
+ X509ExtendedKeyManager x509ExtendedKeyManager = CertParsingUtils.keyManager(certs, privateKey, new char[0]);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(new X509ExtendedKeyManager[] { x509ExtendedKeyManager },
new TrustManager[] { new TrustAllTrustManager(false) }, new SecureRandom());
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java
index 3e05c88953a..bebf74a368f 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java
@@ -5,30 +5,17 @@
*/
package org.elasticsearch.xpack.ssl;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.Extension;
-import org.bouncycastle.asn1.x509.Time;
-import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
-import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
-import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+
import org.elasticsearch.ElasticsearchException;
-import org.elasticsearch.common.network.InetAddressHelper;
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
-import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.env.TestEnvironment;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.SecuritySettingsSource;
-import org.elasticsearch.test.SecuritySettingsSourceField;
import org.elasticsearch.transport.Transport;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
import org.elasticsearch.xpack.core.ssl.SSLService;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;
@@ -42,11 +29,9 @@ import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
-import java.security.KeyPair;
import java.security.KeyStore;
-import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
-import java.util.Locale;
+import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import static org.hamcrest.Matchers.containsString;
@@ -61,6 +46,7 @@ public class SSLReloadIntegTests extends SecurityIntegTestCase {
@Override
public Settings nodeSettings(int nodeOrdinal) {
+ //Node starts with testnode.jks
if (nodeStorePath == null) {
Path origPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
Path tempDir = createTempDir();
@@ -94,18 +80,12 @@ public class SSLReloadIntegTests extends SecurityIntegTestCase {
}
public void testThatSSLConfigurationReloadsOnModification() throws Exception {
- KeyPair keyPair = CertUtils.generateKeyPair(randomFrom(1024, 2048));
- X509Certificate certificate = getCertificate(keyPair);
- KeyStore keyStore = KeyStore.getInstance("jks");
- keyStore.load(null, null);
- keyStore.setKeyEntry("key", keyPair.getPrivate(), SecuritySettingsSourceField.TEST_PASSWORD.toCharArray(),
- new Certificate[] { certificate });
- Path keystorePath = createTempDir().resolve("newcert.jks");
- try (OutputStream out = Files.newOutputStream(keystorePath)) {
- keyStore.store(out, SecuritySettingsSourceField.TEST_PASSWORD.toCharArray());
- }
+ Path keystorePath = createTempDir().resolve("testnode_updated.jks");
+ Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.jks"), keystorePath);
+ X509Certificate certificate = CertParsingUtils.readX509Certificates(Collections.singletonList(getDataPath
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt")))[0];
MockSecureSettings secureSettings = new MockSecureSettings();
- secureSettings.setString("xpack.ssl.keystore.secure_password", SecuritySettingsSourceField.TEST_PASSWORD);
+ secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
secureSettings.setString("xpack.ssl.truststore.secure_password", "testnode");
Settings settings = Settings.builder()
.put("path.home", createTempDir())
@@ -125,7 +105,6 @@ public class SSLReloadIntegTests extends SecurityIntegTestCase {
} catch (SSLHandshakeException | SocketException expected) {
logger.trace("expected exception", expected);
}
-
KeyStore nodeStore = KeyStore.getInstance("jks");
try (InputStream in = Files.newInputStream(nodeStorePath)) {
nodeStore.load(in, "testnode".toCharArray());
@@ -140,7 +119,6 @@ public class SSLReloadIntegTests extends SecurityIntegTestCase {
} catch (AtomicMoveNotSupportedException e) {
Files.move(path, nodeStorePath, StandardCopyOption.REPLACE_EXISTING);
}
-
CountDownLatch latch = new CountDownLatch(1);
assertBusy(() -> {
try (SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(address.getAddress(), address.getPort())) {
@@ -162,23 +140,4 @@ public class SSLReloadIntegTests extends SecurityIntegTestCase {
});
latch.await();
}
-
- private X509Certificate getCertificate(KeyPair keyPair) throws Exception {
- final DateTime notBefore = new DateTime(DateTimeZone.UTC);
- final DateTime notAfter = notBefore.plusYears(1);
- X500Name subject = new X500Name("CN=random cert");
- JcaX509v3CertificateBuilder builder =
- new JcaX509v3CertificateBuilder(subject, CertUtils.getSerial(),
- new Time(notBefore.toDate(), Locale.ROOT), new Time(notAfter.toDate(), Locale.ROOT), subject, keyPair.getPublic());
-
- JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
- builder.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(keyPair.getPublic()));
- builder.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(keyPair.getPublic()));
- builder.addExtension(Extension.subjectAlternativeName, false,
- CertUtils.getSubjectAlternativeNames(true, Sets.newHashSet(InetAddressHelper.getAllAddresses())));
-
- ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").build(keyPair.getPrivate());
- X509CertificateHolder certificateHolder = builder.build(signer);
- return new JcaX509CertificateConverter().getCertificate(certificateHolder);
- }
}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java
index 4e76e59e596..085e0c187e7 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java
@@ -6,9 +6,8 @@
package org.elasticsearch.xpack.ssl;
import org.apache.logging.log4j.message.ParameterizedMessage;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.unit.TimeValue;
@@ -17,7 +16,8 @@ import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.transport.Transport;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
+import org.elasticsearch.xpack.core.ssl.PemUtils;
import org.elasticsearch.xpack.core.ssl.RestrictedTrustManager;
import org.elasticsearch.xpack.core.ssl.SSLService;
import org.junit.AfterClass;
@@ -26,19 +26,15 @@ import org.junit.BeforeClass;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
-import javax.security.auth.x500.X500Principal;
-import java.io.BufferedWriter;
import java.io.IOException;
import java.net.SocketException;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
-import static org.elasticsearch.xpack.core.ssl.CertUtils.generateSignedCertificate;
import static org.hamcrest.Matchers.is;
/**
@@ -54,7 +50,6 @@ public class SSLTrustRestrictionsTests extends SecurityIntegTestCase {
* Use a small keysize for performance, since the keys are only used in this test, but a large enough keysize
* to get past the SSL algorithm checker
*/
- private static final int KEYSIZE = 1024;
private static final int RESOURCE_RELOAD_MILLIS = 3;
private static final TimeValue MAX_WAIT_RELOAD = TimeValue.timeValueSeconds(1);
@@ -78,13 +73,29 @@ public class SSLTrustRestrictionsTests extends SecurityIntegTestCase {
@BeforeClass
public static void setupCertificates() throws Exception {
configPath = createTempDir();
+ Path caCertPath = PathUtils.get(SSLTrustRestrictionsTests.class.getResource
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca.crt").toURI());
+ X509Certificate caCert = CertParsingUtils.readX509Certificates(Collections.singletonList(caCertPath))[0];
+ Path caKeyPath = PathUtils.get(SSLTrustRestrictionsTests.class.getResource
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/ca.key").toURI());
+ PrivateKey caKey = PemUtils.readPrivateKey(caKeyPath, ""::toCharArray);
+ ca = new CertificateInfo(caKey, caKeyPath, caCert, caCertPath);
- final KeyPair caPair = CertUtils.generateKeyPair(KEYSIZE);
- final X509Certificate caCert = CertUtils.generateCACertificate(new X500Principal("cn=CertAuth"), caPair, 30);
- ca = writeCertificates("ca", caPair.getPrivate(), caCert);
+ Path trustedCertPath = PathUtils.get(SSLTrustRestrictionsTests.class.getResource
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/trusted.crt").toURI());
+ X509Certificate trustedX509Certificate = CertParsingUtils.readX509Certificates(Collections.singletonList(trustedCertPath))[0];
+ Path trustedKeyPath = PathUtils.get(SSLTrustRestrictionsTests.class.getResource
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/trusted.key").toURI());
+ PrivateKey trustedKey = PemUtils.readPrivateKey(trustedKeyPath, ""::toCharArray);
+ trustedCert = new CertificateInfo(trustedKey, trustedKeyPath, trustedX509Certificate, trustedCertPath);
- trustedCert = generateCertificate("trusted", "node.trusted");
- untrustedCert = generateCertificate("untrusted", "someone.else");
+ Path untrustedCertPath = PathUtils.get(SSLTrustRestrictionsTests.class.getResource
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/untrusted.crt").toURI());
+ X509Certificate untrustedX509Certificate = CertParsingUtils.readX509Certificates(Collections.singletonList(untrustedCertPath))[0];
+ Path untrustedKeyPath = PathUtils.get(SSLTrustRestrictionsTests.class.getResource
+ ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/nodes/untrusted.key").toURI());
+ PrivateKey untrustedKey = PemUtils.readPrivateKey(untrustedKeyPath, ""::toCharArray);
+ untrustedCert = new CertificateInfo(untrustedKey, untrustedKeyPath, untrustedX509Certificate, untrustedCertPath);
nodeSSL = Settings.builder()
.put("xpack.security.transport.ssl.enabled", true)
@@ -204,31 +215,6 @@ public class SSLTrustRestrictionsTests extends SecurityIntegTestCase {
}
}
-
- private static CertificateInfo generateCertificate(String name, String san) throws Exception {
- final KeyPair keyPair = CertUtils.generateKeyPair(KEYSIZE);
- final X500Principal principal = new X500Principal("cn=" + name);
- final GeneralNames altNames = new GeneralNames(CertUtils.createCommonName(san));
- final X509Certificate cert = generateSignedCertificate(principal, altNames, keyPair, ca.getCertificate(), ca.getKey(), 30);
- return writeCertificates(name, keyPair.getPrivate(), cert);
- }
-
- private static CertificateInfo writeCertificates(String name, PrivateKey key, X509Certificate cert) throws IOException {
- final Path keyPath = writePem(key, name + ".key");
- final Path certPath = writePem(cert, name + ".crt");
- return new CertificateInfo(key, keyPath, cert, certPath);
- }
-
- private static Path writePem(Object obj, String filename) throws IOException {
- Path path = configPath.resolve(filename);
- Files.deleteIfExists(path);
- try (BufferedWriter out = Files.newBufferedWriter(path);
- JcaPEMWriter pemWriter = new JcaPEMWriter(out)) {
- pemWriter.writeObject(obj);
- }
- return path;
- }
-
private static class CertificateInfo {
private final PrivateKey key;
private final Path keyPath;
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/encryption.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/encryption.crt
new file mode 100644
index 00000000000..bb8f70195e2
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/encryption.crt
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDkTCCAnmgAwIBAgIJAKX2TCZPkd/fMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQxGDAWBgNVBAMMD3NhbWwgZW5jcnlwdGlvbjAeFw0xODA0
+MjAxMzIyNDZaFw00NTA5MDUxMzIyNDZaMF8xCzAJBgNVBAYTAkFVMRMwEQYDVQQI
+DApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQx
+GDAWBgNVBAMMD3NhbWwgZW5jcnlwdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAMwb5pLTti9S6qxUeqekurTFX3LWOUFzOo2ywtIo+yEkL3zZTjPx
++VWXpiwMGRrNqf5Aq7ErgHBGit4ZNQkYAacw4biFoAaIj6ZEjEgG9jEuMzn5IA0z
+bQrengEUZMHplCWuEUeSeAb+HqS9SBr1rdv64TRnt7juyXYAVZhuFFxf9ozvGUyn
+8UH9bKjMWiQL6H+I98dqDGVzGyltDmdbHEv63nIKoD5ih6ntyC39VFTTZ8cHPICH
+EOUSrIj3P4qZYJ9UhBGdxskgyqWQMeaKXrhYG0R9wI5aIUq/OA7iVMgveD6Ogd/u
+w8viMTMLukA8bWipUoB6IVNiWykcyuE/TQ8CAwEAAaNQME4wHQYDVR0OBBYEFMq+
+o0Sj0S4PBqdtnzpNyGbW3VlyMB8GA1UdIwQYMBaAFMq+o0Sj0S4PBqdtnzpNyGbW
+3VlyMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFliCFA2jsHu49yX
+Dt+TkE0gUBXQ3ybIxFbXglawZUuidgxcTAKsajXyf5oA5zZKfIFLFRV2yHkmZnUZ
+MhYQ86qKj4qUQqTk/hcnKvPoKibFPBic6TnDzHcF4HMehA/vC8KFppoTNA4gljJP
+gNM3spxC86r9mi7kq7Q1j+9dWv9LhhCo7QVAJQP68iFmL7EyFOgqO3otlqtaWWmt
+ju2x/T9Oyx0WZkwDdCvbqgBWFIqc8h3moFG3vEVU3GuS4oox4DuRZHvY+QGvbDXz
+FdIiIpRlNs3ecQy4268diX8wPd+xFH1i1/OEZq9opYvz3Xzta54O1Ae//FcnIbFw
+gA+vGPQ=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/encryption.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/encryption.key
new file mode 100644
index 00000000000..f454a863793
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/encryption.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDMG+aS07YvUuqs
+VHqnpLq0xV9y1jlBczqNssLSKPshJC982U4z8flVl6YsDBkazan+QKuxK4BwRore
+GTUJGAGnMOG4haAGiI+mRIxIBvYxLjM5+SANM20K3p4BFGTB6ZQlrhFHkngG/h6k
+vUga9a3b+uE0Z7e47sl2AFWYbhRcX/aM7xlMp/FB/WyozFokC+h/iPfHagxlcxsp
+bQ5nWxxL+t5yCqA+Yoep7cgt/VRU02fHBzyAhxDlEqyI9z+KmWCfVIQRncbJIMql
+kDHmil64WBtEfcCOWiFKvzgO4lTIL3g+joHf7sPL4jEzC7pAPG1oqVKAeiFTYlsp
+HMrhP00PAgMBAAECggEAUOGVgwVmImanG9b2K8x5N/0mj6kYUzlIMLJvxTv8F+vw
+7XZnKOpwNVy8uqOopxhsjpYt8y0b3mH10YEHpSzgKtKR/77j5PLkiayMMlaf5Gk8
+X3K7IsAIK9B/qEnei4D19eB+dHA0JAE7P2jKU/SbCprl9xBKm3v0VVBYmui0JM4k
+A9bKgAWj8M2UBGMDOXyNVLn0o48dLfsspSnCZlq9AN1AkpsGQsnNSY7PfD3b2rC2
+/1Gbxn72hCEXT6pE0brVsya9hfyCESQitktJLz+MWwMQTVqh9c2YLC3E3kzU98qq
+Dj/wpclqLDNpgaLg3oHrMA/hqom6ADTQrZNvHM84UQKBgQD+LJIYKm6NE+YFwpmO
+CqTpBai197GL+uIRBAmwm1O0T0rKEDa6TbFEiOhfrkwhLjmuxTzlnLUtHrovVPZo
+xT+PKPfc4HY+EmswdBmxA81KN2sHr3u0qS6MLc8XH1NG49yBCCK6C49QkHoQ2HpC
+LE1yUpVoyv32FJtSTR83MerfFQKBgQDNk0J28V5vsHO9O1ZtG29ogVrkFz/WlHov
+B5MzDbpduCzrwDUp62h+QsCr1cZLQcMgm/nSe4ooCYnXZF5Srhcqz6Wmuz0F3kuT
+gW1cXj8Go27jHktfnukBRaZxc43W0lPu5032a0BmOVIvuJ/+e0CaqPvc/ROONyjQ
+BFidPolkkwKBgALZvx20RB8i7P59izlTlzvhy12XFI+sVaK5N96aL1sjVIRloCeA
+vY82Ndz02He6y/zQy3kLw+Boqs/jFQxhwe+6FuWMQuc5T6hwdOVOVJwTeQjSCAIj
+r5j03pC00jtGTO/JhpItlQLjS+sqclyRoKC6mmBdfnGnE4LdyI7W6XptAoGBAIjw
+d23UCxxLZk2/oSq9A9GRmYInGpdOALYjTaLMmkCj1wiT2NY7wjeZL89Hb/fhrqGi
+RSA4uydAc1nPuiVJYpVaDPar81JdaeqwZLEK9uDtLYiNPZhMutnmE6GvX+Sh5tdV
+rVFg0F1IAb9YNPvIDpj3yA7FZqlthPpMatsUNWGRAoGAaLTl3JIYCyL9KAhh018M
+bXabn/MAZblAjNYjNe5kRedOZLBsOn6LZ8pr0xjfdLWzmG73UCobBwG98ytF+HAJ
+Lv+7JiCanSxOn77hmm1QTAPQtOMsqiioZJMtDGAleCsvJ7EucOT9B82JcZdFWREd
+49fCrJvSWeyC/2VvY13d8ek=
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_1024.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_1024.crt
new file mode 100644
index 00000000000..600f3f52d71
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_1024.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICuTCCAnegAwIBAgIJANmjfXJkQMjMMAsGCWCGSAFlAwQDAjAUMRIwEAYDVQQD
+DAlzYW1sLXRlc3QwHhcNMTgwNDIwMTQzNjI2WhcNNDUwOTA1MTQzNjI2WjAUMRIw
+EAYDVQQDDAlzYW1sLXRlc3QwggG4MIIBLAYHKoZIzjgEATCCAR8CgYEA/8pxx/TX
+8KJ2qqVFlzo17jY4GmbtLybpqJQjt89HvmAB0eezPGH86/h6Vz17owRJbPPcHV9l
+qfgI+5WRRlk5J9Ps0e6jOHzQbnhdM+jnLh1UWrw1fqZpBwu2DGStino9kRCrQB/J
+zKfJTjBQ9G/PZoDWDjDgrMJG3zfyn+oy4U0CFQCzALSwPEDhLR7vcOO6uvRd9UxK
+GQKBgQC7/eMV/4frAl9QCxDNjWXO04kfKGonQzu1Zj4213Igh3Tb86vSKyIfmQbA
+urFuFY/w6UZY/zTeHCpo49Bwf+m/C1dtqe1X6P437qt5AKNZPG1L4YyGtTgE2YzL
+now4sHM1VH2RBsHTa/CElH4YYJQdz21Xh+LtSEmhC92+y7z1DwOBhQACgYEAq+dc
+sfITP88PeA7Gw/caNVa/rKcm3C5B5GLk3eLQkipU+ilax71uTRQMbSOSisW0+xgo
+20CBB2ImNWPMT5gCHPh1owSXT7aqjNCYlcdX+mTY7FWtEa5kPjpRl2ZLXDYtgkwq
+JozVZtcra5G77g6UDDfdPcY4LBzLoQ8N6jh9CmKjUDBOMB0GA1UdDgQWBBT/nFyW
+NyCimEOxlU9hOnp1BhucWTAfBgNVHSMEGDAWgBT/nFyWNyCimEOxlU9hOnp1Bhuc
+WTAMBgNVHRMEBTADAQH/MAsGCWCGSAFlAwQDAgMvADAsAhRIYvFQeOeTvAzQvE4x
+3T5D9mgynQIUZlAH0EU+oeQcbKtT9G9359+H8oY=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_1024.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_1024.key
new file mode 100644
index 00000000000..b79904c247f
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_1024.key
@@ -0,0 +1,21 @@
+-----BEGIN DSA PARAMETERS-----
+MIIBHwKBgQD/ynHH9NfwonaqpUWXOjXuNjgaZu0vJumolCO3z0e+YAHR57M8Yfzr
++HpXPXujBEls89wdX2Wp+Aj7lZFGWTkn0+zR7qM4fNBueF0z6OcuHVRavDV+pmkH
+C7YMZK2Kej2REKtAH8nMp8lOMFD0b89mgNYOMOCswkbfN/Kf6jLhTQIVALMAtLA8
+QOEtHu9w47q69F31TEoZAoGBALv94xX/h+sCX1ALEM2NZc7TiR8oaidDO7VmPjbX
+ciCHdNvzq9IrIh+ZBsC6sW4Vj/DpRlj/NN4cKmjj0HB/6b8LV22p7Vfo/jfuq3kA
+o1k8bUvhjIa1OATZjMuejDiwczVUfZEGwdNr8ISUfhhglB3PbVeH4u1ISaEL3b7L
+vPUP
+-----END DSA PARAMETERS-----
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQD/ynHH9NfwonaqpUWXOjXuNjgaZu0vJumolCO3z0e+YAHR57M8
+Yfzr+HpXPXujBEls89wdX2Wp+Aj7lZFGWTkn0+zR7qM4fNBueF0z6OcuHVRavDV+
+pmkHC7YMZK2Kej2REKtAH8nMp8lOMFD0b89mgNYOMOCswkbfN/Kf6jLhTQIVALMA
+tLA8QOEtHu9w47q69F31TEoZAoGBALv94xX/h+sCX1ALEM2NZc7TiR8oaidDO7Vm
+PjbXciCHdNvzq9IrIh+ZBsC6sW4Vj/DpRlj/NN4cKmjj0HB/6b8LV22p7Vfo/jfu
+q3kAo1k8bUvhjIa1OATZjMuejDiwczVUfZEGwdNr8ISUfhhglB3PbVeH4u1ISaEL
+3b7LvPUPAoGBAKvnXLHyEz/PD3gOxsP3GjVWv6ynJtwuQeRi5N3i0JIqVPopWse9
+bk0UDG0jkorFtPsYKNtAgQdiJjVjzE+YAhz4daMEl0+2qozQmJXHV/pk2OxVrRGu
+ZD46UZdmS1w2LYJMKiaM1WbXK2uRu+4OlAw33T3GOCwcy6EPDeo4fQpiAhRRr/H0
+5gsFm98/sSGEB0FnJxwtoQ==
+-----END DSA PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_2048.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_2048.crt
new file mode 100644
index 00000000000..dde37da25f3
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_2048.crt
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIEYDCCBAWgAwIBAgIJANqVfS+jJN18MAsGCWCGSAFlAwQDAjAUMRIwEAYDVQQD
+DAlzYW1sLXRlc3QwHhcNMTgwNDIwMTQzNjE0WhcNNDUwOTA1MTQzNjE0WjAUMRIw
+EAYDVQQDDAlzYW1sLXRlc3QwggNGMIICOQYHKoZIzjgEATCCAiwCggEBAK4397p/
+INfVcEcE30XnRMyhouv6sGSIEugHQm34goq7MwciNQprVeFb1dt7WGA7INd4Jxil
+Hb1HGFfQxDH4F/CsNPGHLrdLgN35f7VbykGjnV2KoNMW77WwIt0d23KQ9xWG/sCb
+F25yvHDQp0Bl8rzq65l9q2rmpbRThUyDmG5J507bLmeAdqU94eOt8OHauRFo1acu
+ZQueNiOL9Ky+0Xog0CWSBkz3P4CzXAr8yaWKmtRVbRAYjrcNqetfJck3nrjgfipW
+0vugMvO2PDMH1AR2GKvezPSSneriSzaF/x7QKuMLQGn3PElm+R1ubwqPOkb7mYwE
+5nU3L0MDXhIcTwMCIQDYLmAG7+eZx9vxVtmt3dJETBoD2nxdCzuv7ICkEnBiAQKC
+AQB8kbV81nMDCYAvSgjdgXmCE4MrmfcPKAGV1MWTzMpLul81am9n6Z14WHZnyNOC
+fcgjwYphKzHFvmIC9YLKN5EXDmkEf9YK0MbTt1KaGhgMW3fHfQr981wHpL/Ld7nm
+896trhvE1h/qgOjQDsYRxTbeGETDglWH2JChJIOsrgpmoZBSclQPtKtbwHo+YkFZ
+lL7tcn7gOWsUwOSE/OlO2nD9ClfHmsGw11Yaoj9M3Enj+99XKMSWlBwulwdBVTIW
+IuH2Z33scpIPSsXv0AXw7XI9whCTR/8aKbSUFcd4YvtATzyvPnlF048JEHqxjMFA
++1EGpMblEv9thmpB2VeRv5AnA4IBBQACggEAL0WV13soENtKJQ3NRvokIWJN2Hfh
+SFogAEVgFdywA1rV7j8YRgG93nLauI3TYIN9lLYlXVTWQT9s69XcQEcwSRrz8DZ0
+8zhCnZ12pCowWLh3jIEG8OZOC8H3nKJLuPQvgvaFLLucecQJSFFkxp/kIdiOEMFk
+o30vby2hn6z/OwGb+nRawN1Qpbpe+go7fwB+sUd+ked2UfvG344tp7fttMWgMS/H
+zz1s49NzprfM0kGUpwW2NkMAiJL4Bg94W7VuIHeQP5nvbnVnPZq0ehohwcjp0SkB
+8WvzOMnP5VNRsERJsZocvcvurP9cOqrlaQDjVw90JXsBUy9Spl0dy2TGA6NQME4w
+HQYDVR0OBBYEFNY7sXlXy2ydEJm+QrwWtbUzWy+rMB8GA1UdIwQYMBaAFNY7sXlX
+y2ydEJm+QrwWtbUzWy+rMAwGA1UdEwQFMAMBAf8wCwYJYIZIAWUDBAMCA0gAMEUC
+IQDTdKo5ocf2X9vHFYedf9Gh3v8+muXrcF+OUP7hMC5y/QIgMbVw49iiqniRHg/H
+6qWdx7hZWb64QPKLrwdGdwMIvJo=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_2048.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_2048.key
new file mode 100644
index 00000000000..7b99f406b4b
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_2048.key
@@ -0,0 +1,34 @@
+-----BEGIN DSA PARAMETERS-----
+MIICLAKCAQEArjf3un8g19VwRwTfRedEzKGi6/qwZIgS6AdCbfiCirszByI1CmtV
+4VvV23tYYDsg13gnGKUdvUcYV9DEMfgX8Kw08Ycut0uA3fl/tVvKQaOdXYqg0xbv
+tbAi3R3bcpD3FYb+wJsXbnK8cNCnQGXyvOrrmX2raualtFOFTIOYbknnTtsuZ4B2
+pT3h463w4dq5EWjVpy5lC542I4v0rL7ReiDQJZIGTPc/gLNcCvzJpYqa1FVtEBiO
+tw2p618lyTeeuOB+KlbS+6Ay87Y8MwfUBHYYq97M9JKd6uJLNoX/HtAq4wtAafc8
+SWb5HW5vCo86RvuZjATmdTcvQwNeEhxPAwIhANguYAbv55nH2/FW2a3d0kRMGgPa
+fF0LO6/sgKQScGIBAoIBAHyRtXzWcwMJgC9KCN2BeYITgyuZ9w8oAZXUxZPMyku6
+XzVqb2fpnXhYdmfI04J9yCPBimErMcW+YgL1gso3kRcOaQR/1grQxtO3UpoaGAxb
+d8d9Cv3zXAekv8t3uebz3q2uG8TWH+qA6NAOxhHFNt4YRMOCVYfYkKEkg6yuCmah
+kFJyVA+0q1vAej5iQVmUvu1yfuA5axTA5IT86U7acP0KV8eawbDXVhqiP0zcSeP7
+31coxJaUHC6XB0FVMhYi4fZnfexykg9Kxe/QBfDtcj3CEJNH/xoptJQVx3hi+0BP
+PK8+eUXTjwkQerGMwUD7UQakxuUS/22GakHZV5G/kCc=
+-----END DSA PARAMETERS-----
+-----BEGIN DSA PRIVATE KEY-----
+MIIDVQIBAAKCAQEArjf3un8g19VwRwTfRedEzKGi6/qwZIgS6AdCbfiCirszByI1
+CmtV4VvV23tYYDsg13gnGKUdvUcYV9DEMfgX8Kw08Ycut0uA3fl/tVvKQaOdXYqg
+0xbvtbAi3R3bcpD3FYb+wJsXbnK8cNCnQGXyvOrrmX2raualtFOFTIOYbknnTtsu
+Z4B2pT3h463w4dq5EWjVpy5lC542I4v0rL7ReiDQJZIGTPc/gLNcCvzJpYqa1FVt
+EBiOtw2p618lyTeeuOB+KlbS+6Ay87Y8MwfUBHYYq97M9JKd6uJLNoX/HtAq4wtA
+afc8SWb5HW5vCo86RvuZjATmdTcvQwNeEhxPAwIhANguYAbv55nH2/FW2a3d0kRM
+GgPafF0LO6/sgKQScGIBAoIBAHyRtXzWcwMJgC9KCN2BeYITgyuZ9w8oAZXUxZPM
+yku6XzVqb2fpnXhYdmfI04J9yCPBimErMcW+YgL1gso3kRcOaQR/1grQxtO3Upoa
+GAxbd8d9Cv3zXAekv8t3uebz3q2uG8TWH+qA6NAOxhHFNt4YRMOCVYfYkKEkg6yu
+CmahkFJyVA+0q1vAej5iQVmUvu1yfuA5axTA5IT86U7acP0KV8eawbDXVhqiP0zc
+SeP731coxJaUHC6XB0FVMhYi4fZnfexykg9Kxe/QBfDtcj3CEJNH/xoptJQVx3hi
++0BPPK8+eUXTjwkQerGMwUD7UQakxuUS/22GakHZV5G/kCcCggEAL0WV13soENtK
+JQ3NRvokIWJN2HfhSFogAEVgFdywA1rV7j8YRgG93nLauI3TYIN9lLYlXVTWQT9s
+69XcQEcwSRrz8DZ08zhCnZ12pCowWLh3jIEG8OZOC8H3nKJLuPQvgvaFLLucecQJ
+SFFkxp/kIdiOEMFko30vby2hn6z/OwGb+nRawN1Qpbpe+go7fwB+sUd+ked2UfvG
+344tp7fttMWgMS/Hzz1s49NzprfM0kGUpwW2NkMAiJL4Bg94W7VuIHeQP5nvbnVn
+PZq0ehohwcjp0SkB8WvzOMnP5VNRsERJsZocvcvurP9cOqrlaQDjVw90JXsBUy9S
+pl0dy2TGAwIgaDj3hOeYYK3x/K4chyuu/XFG107+R8lhsheS+PeTkqw=
+-----END DSA PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_3072.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_3072.crt
new file mode 100644
index 00000000000..4f79ec00267
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_3072.crt
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF4TCCBYagAwIBAgIJANrEy+H3aIfjMAsGCWCGSAFlAwQDAjAUMRIwEAYDVQQD
+DAlzYW1sLXRlc3QwHhcNMTgwNDIwMTQzNjQ1WhcNNDUwOTA1MTQzNjQ1WjAUMRIw
+EAYDVQQDDAlzYW1sLXRlc3QwggTHMIIDOgYHKoZIzjgEATCCAy0CggGBAP82FCLU
++LbuyR9z6mXKSbe0cLNnA3QMYNeu0T2Sg5EZrpkrWLt89241D9p25r/woMrdbx0Q
+IveLkV2D2vNGflPHJTI5QhlLFJLMi04JHD8HVcKUW3dWlY1inn1p3Ppxr9/siP8/
++78NivOI+PLErHf4d3aJB86ayggWmpwn6Fw3xfEYorAY5pWx67JkXJx+339RH8Dy
+3uL/V3joyf+9Qe58EqjfwXSRboOrwEMxlHKSKn0m0juaQ+tcjiRF7ftwPNDCYjtN
+YK/OYqKdUGBE8hycB4SloH16hZCZrq7JCnh4ux8iO58BTZGwDPUEpqsYB0bXq0gb
+eMQuh0OUxCc9yge9XuuUwYm9m47xGD9+HAuwBBXQk6nEBxEdilHle9dVeAbZV4bJ
+0/P4I3ptPK2nmc6FJpBpJ8BM90DvCkdYV2jLRoGs/kDQlxpYuHmnTKjeuaUmyAPo
+cbM8rzgtxaETwSYI2wyJITAZb2yE7uTQDCu/qPbHQ358JspVpPskGM1ZDQIhAM1L
+jjFPqRbfK//2/PfyQ/4YKN5LHkWE/AabiIGF7r8HAoIBgQCUK79jRWpSVLNoXK59
+42pNwzKO5Uqn7ggcwqn2Ipy2rTtp9+rh9UOyGmWRF1JHuQ2jia+hq2ZOSnuMJ4r6
+aRjaQHmjysYM0ZTBtgKrcqmukwMWf8h3Flsza5GkQC79XwMBe5M2x61p2IY+IXfq
+2dY1AhhXAIIQbOtDmNgQdBMkTk01/Yvp5b6zaJ0+/IZQ6nPQr3jQa4W37WusNOGn
+Gspiq7jG+omrpN1CJkzcESxwFjsI6x07IxJ9Tg3UUf5dr8OFCGEUFo0cXzBFSr3i
+FO3N0iynaOpWxZ8RLevA30bnG69pVWfvnKm36iEpMPHV/acuj3LFx2SQpOy7yF5g
+q+F52EWBbs9FjKQ5yx77OEKPoXx2ek0CdGwNwI1cVv8XYo7zN3PDyEniM/YFJqWF
+jyW0ztKteGPIfV87JKUfply2UXbEIymYomcfNfVOf2JmN05zE0zpjghcGSSHkeId
+6uU4mTypuGNi823/k/1JkZhsaXxbpp+78FeFkyTV89GHIDYDggGFAAKCAYAZG6jf
+NEVl1ZzxEuFpDtCaiO+hDPJ1qURAFUaXIg/kt+U1hBjMlicjb/6Rf587O2RtR8nN
+GEGBDa5CGEQMicjKawze/Wwf4QpPVw0ZUQ6bbidIlFBmpQ/+yad3f/amE72MT988
+Dfd8oHPRMhltNljgU66WgNSG1CTd6trVWgHxXARIQMIxBtl3b5UgYtxj6mVrOxR2
+QG+K/HiXVgBMkzafUe5AzF+IkQB1xXuBFQDuh7ULBBKS/Ia2klQ3BkdWsVKxVpzc
+jR2vCEkNEoXpRsIqwBkYEitz/YXKgfNoDFw4sNb8Vyu1vZRszCVXrrrbgvt5SQ46
+YcuqBlbbuavoU1qgwrBvCAHbMkKghb0Y5QeqVncVyHM0dqG66DEwiLjitc1qLqk6
+WZU821KnB5mT1wkbktdH7Kw0RICb5R1CKBdNJTAVyRANPXi9S/X/qp3T2tkrK8Gl
+EopTONKd9A0DRJ9nxSSkrN0VfOkOM9oeV9LiNnPMBglDhpGIr/zO3GF6gT6jUDBO
+MB0GA1UdDgQWBBSTwbajNJiB9l9AIfvR97CMW3B/3jAfBgNVHSMEGDAWgBSTwbaj
+NJiB9l9AIfvR97CMW3B/3jAMBgNVHRMEBTADAQH/MAsGCWCGSAFlAwQDAgNIADBF
+AiB+OJSiXfQofQO11Xmo7m0Jf9nIwrQTWTb5nfAJmAz88AIhAIYho94NHHN6KBqS
+YPg4RrxidM/RFy/aZ1bIeQwwpByY
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_3072.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_3072.key
new file mode 100644
index 00000000000..34b11983653
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_DSA_3072.key
@@ -0,0 +1,48 @@
+-----BEGIN DSA PARAMETERS-----
+MIIDLQKCAYEA/zYUItT4tu7JH3PqZcpJt7Rws2cDdAxg167RPZKDkRmumStYu3z3
+bjUP2nbmv/Cgyt1vHRAi94uRXYPa80Z+U8clMjlCGUsUksyLTgkcPwdVwpRbd1aV
+jWKefWnc+nGv3+yI/z/7vw2K84j48sSsd/h3dokHzprKCBaanCfoXDfF8RiisBjm
+lbHrsmRcnH7ff1EfwPLe4v9XeOjJ/71B7nwSqN/BdJFug6vAQzGUcpIqfSbSO5pD
+61yOJEXt+3A80MJiO01gr85iop1QYETyHJwHhKWgfXqFkJmurskKeHi7HyI7nwFN
+kbAM9QSmqxgHRterSBt4xC6HQ5TEJz3KB71e65TBib2bjvEYP34cC7AEFdCTqcQH
+ER2KUeV711V4BtlXhsnT8/gjem08raeZzoUmkGknwEz3QO8KR1hXaMtGgaz+QNCX
+Gli4eadMqN65pSbIA+hxszyvOC3FoRPBJgjbDIkhMBlvbITu5NAMK7+o9sdDfnwm
+ylWk+yQYzVkNAiEAzUuOMU+pFt8r//b89/JD/hgo3kseRYT8BpuIgYXuvwcCggGB
+AJQrv2NFalJUs2hcrn3jak3DMo7lSqfuCBzCqfYinLatO2n36uH1Q7IaZZEXUke5
+DaOJr6GrZk5Ke4wnivppGNpAeaPKxgzRlMG2Aqtyqa6TAxZ/yHcWWzNrkaRALv1f
+AwF7kzbHrWnYhj4hd+rZ1jUCGFcAghBs60OY2BB0EyROTTX9i+nlvrNonT78hlDq
+c9CveNBrhbfta6w04acaymKruMb6iauk3UImTNwRLHAWOwjrHTsjEn1ODdRR/l2v
+w4UIYRQWjRxfMEVKveIU7c3SLKdo6lbFnxEt68DfRucbr2lVZ++cqbfqISkw8dX9
+py6PcsXHZJCk7LvIXmCr4XnYRYFuz0WMpDnLHvs4Qo+hfHZ6TQJ0bA3AjVxW/xdi
+jvM3c8PISeIz9gUmpYWPJbTO0q14Y8h9XzskpR+mXLZRdsQjKZiiZx819U5/YmY3
+TnMTTOmOCFwZJIeR4h3q5TiZPKm4Y2Lzbf+T/UmRmGxpfFumn7vwV4WTJNXz0Ycg
+Ng==
+-----END DSA PARAMETERS-----
+-----BEGIN DSA PRIVATE KEY-----
+MIIE1wIBAAKCAYEA/zYUItT4tu7JH3PqZcpJt7Rws2cDdAxg167RPZKDkRmumStY
+u3z3bjUP2nbmv/Cgyt1vHRAi94uRXYPa80Z+U8clMjlCGUsUksyLTgkcPwdVwpRb
+d1aVjWKefWnc+nGv3+yI/z/7vw2K84j48sSsd/h3dokHzprKCBaanCfoXDfF8Rii
+sBjmlbHrsmRcnH7ff1EfwPLe4v9XeOjJ/71B7nwSqN/BdJFug6vAQzGUcpIqfSbS
+O5pD61yOJEXt+3A80MJiO01gr85iop1QYETyHJwHhKWgfXqFkJmurskKeHi7HyI7
+nwFNkbAM9QSmqxgHRterSBt4xC6HQ5TEJz3KB71e65TBib2bjvEYP34cC7AEFdCT
+qcQHER2KUeV711V4BtlXhsnT8/gjem08raeZzoUmkGknwEz3QO8KR1hXaMtGgaz+
+QNCXGli4eadMqN65pSbIA+hxszyvOC3FoRPBJgjbDIkhMBlvbITu5NAMK7+o9sdD
+fnwmylWk+yQYzVkNAiEAzUuOMU+pFt8r//b89/JD/hgo3kseRYT8BpuIgYXuvwcC
+ggGBAJQrv2NFalJUs2hcrn3jak3DMo7lSqfuCBzCqfYinLatO2n36uH1Q7IaZZEX
+Uke5DaOJr6GrZk5Ke4wnivppGNpAeaPKxgzRlMG2Aqtyqa6TAxZ/yHcWWzNrkaRA
+Lv1fAwF7kzbHrWnYhj4hd+rZ1jUCGFcAghBs60OY2BB0EyROTTX9i+nlvrNonT78
+hlDqc9CveNBrhbfta6w04acaymKruMb6iauk3UImTNwRLHAWOwjrHTsjEn1ODdRR
+/l2vw4UIYRQWjRxfMEVKveIU7c3SLKdo6lbFnxEt68DfRucbr2lVZ++cqbfqISkw
+8dX9py6PcsXHZJCk7LvIXmCr4XnYRYFuz0WMpDnLHvs4Qo+hfHZ6TQJ0bA3AjVxW
+/xdijvM3c8PISeIz9gUmpYWPJbTO0q14Y8h9XzskpR+mXLZRdsQjKZiiZx819U5/
+YmY3TnMTTOmOCFwZJIeR4h3q5TiZPKm4Y2Lzbf+T/UmRmGxpfFumn7vwV4WTJNXz
+0YcgNgKCAYAZG6jfNEVl1ZzxEuFpDtCaiO+hDPJ1qURAFUaXIg/kt+U1hBjMlicj
+b/6Rf587O2RtR8nNGEGBDa5CGEQMicjKawze/Wwf4QpPVw0ZUQ6bbidIlFBmpQ/+
+yad3f/amE72MT988Dfd8oHPRMhltNljgU66WgNSG1CTd6trVWgHxXARIQMIxBtl3
+b5UgYtxj6mVrOxR2QG+K/HiXVgBMkzafUe5AzF+IkQB1xXuBFQDuh7ULBBKS/Ia2
+klQ3BkdWsVKxVpzcjR2vCEkNEoXpRsIqwBkYEitz/YXKgfNoDFw4sNb8Vyu1vZRs
+zCVXrrrbgvt5SQ46YcuqBlbbuavoU1qgwrBvCAHbMkKghb0Y5QeqVncVyHM0dqG6
+6DEwiLjitc1qLqk6WZU821KnB5mT1wkbktdH7Kw0RICb5R1CKBdNJTAVyRANPXi9
+S/X/qp3T2tkrK8GlEopTONKd9A0DRJ9nxSSkrN0VfOkOM9oeV9LiNnPMBglDhpGI
+r/zO3GF6gT4CIQCRZ5w5NyKQKqR5NaSKp1L1q55ZEC0qFN3/wgQ5KeOcLQ==
+-----END DSA PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_256.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_256.crt
new file mode 100644
index 00000000000..79191a876a5
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_256.crt
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBcDCCARWgAwIBAgIJANz1Ne5UY55RMAoGCCqGSM49BAMCMBQxEjAQBgNVBAMM
+CXNhbWwtdGVzdDAeFw0xODA1MDQwMDIxMDJaFw00NTA5MTkwMDIxMDJaMBQxEjAQ
+BgNVBAMMCXNhbWwtdGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBSfZByz
+t0+zRjEILy841CLkTmD4IOi09xRI41yFjxD4Wwfb+xzAkXCFL9u3sJjwHr7CKKGa
+aXOqYrfnQgAqWoujUDBOMB0GA1UdDgQWBBQoczHwJIhqqu6T8wD+25l8dzGtNjAf
+BgNVHSMEGDAWgBQoczHwJIhqqu6T8wD+25l8dzGtNjAMBgNVHRMEBTADAQH/MAoG
+CCqGSM49BAMCA0kAMEYCIQDCy/yRa/YuYgIA1YHVvlEwkzABqYesH+NIXATDEffI
+OAIhANL3pXUVZTG/UbWsvtORGAK+/I8wvvTnJRNVZsM5p9PD
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_256.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_256.key
new file mode 100644
index 00000000000..08255369668
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_256.key
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgrHS9YdqO4CU0KBaR
+FlO0mV5vDwLNpw81FhM6KZJATcehRANCAAQUn2Qcs7dPs0YxCC8vONQi5E5g+CDo
+tPcUSONchY8Q+FsH2/scwJFwhS/bt7CY8B6+wiihmmlzqmK350IAKlqL
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_384.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_384.crt
new file mode 100644
index 00000000000..c77ef873e03
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_384.crt
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBqzCCATKgAwIBAgIJAMTz13eFY6BxMAoGCCqGSM49BAMCMBQxEjAQBgNVBAMM
+CXNhbWwtdGVzdDAeFw0xODA1MDQwMDIwMzNaFw00NTA5MTkwMDIwMzNaMBQxEjAQ
+BgNVBAMMCXNhbWwtdGVzdDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNGoeQyQzUgc
+brDLsMHYnhHxt59nvJY5Evb50OHXjYWmSkrIHdK7kKVR0Ea5fzDNqy+IsCqZVXaZ
+hzCkfOXVjWX1NHjMIkRjjNV5AZFNkbC5gHibWR9DR0Wc18/Txv+PgaNQME4wHQYD
+VR0OBBYEFB/+GAFqDUKHesgNCKCyGy/FvdHIMB8GA1UdIwQYMBaAFB/+GAFqDUKH
+esgNCKCyGy/FvdHIMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDZwAwZAIwEsge
+vTnFtja0/S1SatbsriyQ6qXyXDIhoManHSr1thqVtKpx8RdaByryV+8/O863AjAS
+4o5vCET9C5UQg85QZizyXO8NzMCS+V/loWyLfjLUL32Fe2UNqxJ4kxeNlZe4p+U=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_384.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_384.key
new file mode 100644
index 00000000000..5d971886860
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_EC_384.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBoi23puIfQZyRaJJoi
+kbyo3fGLueAL4iGkrNMGRLzlglbvFbU8Ktn4tD+VwoRu44ChZANiAATRqHkMkM1I
+HG6wy7DB2J4R8befZ7yWORL2+dDh142FpkpKyB3Su5ClUdBGuX8wzasviLAqmVV2
+mYcwpHzl1Y1l9TR4zCJEY4zVeQGRTZGwuYB4m1kfQ0dFnNfP08b/j4E=
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_1024.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_1024.crt
new file mode 100644
index 00000000000..ea1cb94f5df
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_1024.crt
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB9jCCAV+gAwIBAgIJAOGc4txgrUG3MA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
+BAMMCXNhbWwtdGVzdDAeFw0xODA0MjAxNDE5NDJaFw00NTA5MDUxNDE5NDJaMBQx
+EjAQBgNVBAMMCXNhbWwtdGVzdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+19jSAEiUnBEYtwdMhCEaQLh0p6rZ6TUgK1Jyi+s1bmacsZVvQ6hq7OxnYeqUEm1i
+YffNMvAjonda1SAA4D2sMAd6n6R2Yfvr//tVmT2gCAZjAivSD3fhcPU0a1qHORNo
+0u+64ouqgUWWb9KK09m3tN0xXRaAaSWCTb4kPVgwjhkCAwEAAaNQME4wHQYDVR0O
+BBYEFM/KCl4dXh6OBcusLubKFxXtOy7TMB8GA1UdIwQYMBaAFM/KCl4dXh6OBcus
+LubKFxXtOy7TMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEAIs27ks2K
+glZFV6UTYOuDNFJh7WWpxZIijTuDDuVf/9XHEZUW7dlXhq1u761aI2Eu3BTJVd4D
+5qkwYHNB6m904TZZTy668GQstLyiBNl7J6A3QWPjR1iheIMTZZ9af4yh1QKDeYFA
+52JHcHmiLG2vfJ5ZU6vhMzd02liVRqeVkKw=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_1024.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_1024.key
new file mode 100644
index 00000000000..191721a1b2b
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_1024.key
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANfY0gBIlJwRGLcH
+TIQhGkC4dKeq2ek1ICtScovrNW5mnLGVb0OoauzsZ2HqlBJtYmH3zTLwI6J3WtUg
+AOA9rDAHep+kdmH76//7VZk9oAgGYwIr0g934XD1NGtahzkTaNLvuuKLqoFFlm/S
+itPZt7TdMV0WgGklgk2+JD1YMI4ZAgMBAAECgYAEsKFfgDQ6b+SplW8EL/PyFA/0
+1LGHb7ATQOdcQvAWRgSBl02jmrU4EKruZbpx7A6HMmszACTGEvHWT6u1M6HaHxXV
+BajwkjT2hvLsFurvWZyLJMhgvO5A0/urur6ZjdpYhCcgDW0X2D8B2vOLQmZtQwnL
+mF1wMMNN06ktBL4IQQJBAPWd7blgwnlSSfKY90jltzjY4hHfKr7em6Mz4FdVhYkv
+v7HyOVPtmzVFV8AnYxQVm9VeHvCX6yrjRUrM730IFnsCQQDg+Lh7RWbaxinTQ0cE
+uTBYWF8k0kKwkC4WOh9uo/wWdzYHMlT72LcU1ngUS1AQHdgMTyyAVEHl27DoA8Qp
+tfN7AkEA2vZ87IuHM9MZW23k3hb0PXiUKayTFe+sPlVMBW+XiVKJCaFQXDLx8A6u
+iP5UBJ6y+wdae9BjdSuBJYsHYaapKwJAcR5+3HTsH8sOUsz8U7KuTW26AXC72b3V
+fpWhImfQJJeykfHL64pvnEmuvT2VN1VaQe45iRlUvTg2/qKOKw7zKwJAS5+m+p97
+OrQq/9QzyRni8eXvhlwWA+uImeiNTnFzU/0yeS+gRxF7VeMN7zK9hwVYF8bmhb36
+Yy7x0HZ2DPZZWw==
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_2048.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_2048.crt
new file mode 100644
index 00000000000..8ba12906cf2
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_2048.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC+zCCAeOgAwIBAgIJAMWw9T1InvKNMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
+BAMMCXNhbWwtdGVzdDAeFw0xODA0MjAxNDIwMDBaFw00NTA5MDUxNDIwMDBaMBQx
+EjAQBgNVBAMMCXNhbWwtdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALtG3jAhdGSfju3Y/t6BbDoxqAcL3sgcjPXvQtF3uWD8PxL1PbUEpk3VDg3v
+H4VLMGdwao/YqHpqNJlEoubnSs2Qu/cdnSmpH/W4soa0n+yhNOuV4+GVsxwuztNk
+UArPsFPc4H9e7OcND77RVGAAni3q1/DW/Wp0t8fhVMSmwWBagRtAtZspI7tnPELE
+SSJ+SqlVabaLkwGR1cjH9SjFNJ0hJsBsMs4X0VfabfaewY9RY9BKAJgL9kOVVBZ2
+LKcXM6F8JqpwIj4fgT2NrALxm2cG4AIK/cZKYvtbQdts+qfU/seVoIWwyD7ttQwT
+B1EmojOp2uzlgn1j5wY92nBI9mECAwEAAaNQME4wHQYDVR0OBBYEFLNAhQbO0IlH
+nejoCpunJF0876k/MB8GA1UdIwQYMBaAFLNAhQbO0IlHnejoCpunJF0876k/MAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKIfOrQo2ylg8esZP23F+LY0
+LqgRfei4szMaQM9Pex9jxuS7MJ5rObrErC3lL4l/xYLCGPtfArRbBCyEqhcJuxLW
+4/DQSX7FkKgqWjZ3k3le7IaHEH5eGyIYGCNYs8L1hi4BfrAbQJrAEmBlSOTeJMoh
+GKzfqvdPwNycON2UtZTbgmlGbbH59srFqXIqWBQVsbbTkcG2utdvfRm3Gy2NOJVO
+PMWkfikiClYCYe8dqE1z6CWoQj/2E6mHNiVOfpXPy9E/LbQdU7OkPiG2b5Fsnw+p
+GUGhH0Nx6m7ySTIPk9xt9Bz3SqAiQUrHZoCx6sSR0pfBW/YjNGMxBSJ25xVvR9I=
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_2048.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_2048.key
new file mode 100644
index 00000000000..ef84d7417d8
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_2048.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC7Rt4wIXRkn47t
+2P7egWw6MagHC97IHIz170LRd7lg/D8S9T21BKZN1Q4N7x+FSzBncGqP2Kh6ajSZ
+RKLm50rNkLv3HZ0pqR/1uLKGtJ/soTTrlePhlbMcLs7TZFAKz7BT3OB/XuznDQ++
+0VRgAJ4t6tfw1v1qdLfH4VTEpsFgWoEbQLWbKSO7ZzxCxEkifkqpVWm2i5MBkdXI
+x/UoxTSdISbAbDLOF9FX2m32nsGPUWPQSgCYC/ZDlVQWdiynFzOhfCaqcCI+H4E9
+jawC8ZtnBuACCv3GSmL7W0HbbPqn1P7HlaCFsMg+7bUMEwdRJqIzqdrs5YJ9Y+cG
+PdpwSPZhAgMBAAECggEAeUXIBfT0EWD9xmn5iY7XzctwGrgGGSHb6jp403orEnHm
+SlmDDyCmrMol4sIRcFijTKiQaPwNBdCWpRW8Q7hNSVbLUZfcuSiq6I0lFnQLB8nQ
+oiobOm6dYMey6VMRPh8F+RiUTAbldC2SH6ggclaUF/n2wiAGVJSmmgoBwaKWoNR9
+4rjUuzL/qWxuXAiaitWj7QFM7KAjFml7Z7p9b7MAZnI50mxh3ehp2w2pwqSZ99uG
+TN6U0weLP76krxOx7KD7Y+sDCJEN5RNnH9LL6MBC1L3u23iknwWU6Cl3Jp52NuJE
+UQ661PWGiQqO9EpiTBO1jjthQiggkaOJWmDWQ8IoXQKBgQDwreOoXScQ8x9kBHA7
+QuIKXk/LgQO9V5gwxGARD0/MnRKgrD1E+YdsdsOy7cjGjFBbvSSoqXBSBkHVr2uR
+dqvL7teSdO8o5AG7uUsRTGotNBIpSEWdZYP5Fh/AVQTOE5wf4RlOe3L1uD4sYRdW
+RacPXSrlwQOQtc97yNHOyp+DvwKBgQDHMrt6EyOTtKtgibZ6WQBBEsbGbRe785OU
+wlqgD68PsTyEfpcBsteo5Te72+yOKHwtfXU2JGBtjM0FixTa2dP8KBZPYmBwjaQ1
+rw2Qn7baHWeCOyujvEatLhS3lDX+TdLY3DNR0ZXEyAgkBAc9W1o2YgVT51exxHdt
+op3r+XuN3wKBgQCudFzgXSVEE/Zc+Rqg2goemd4dFJcxV5zpPG6l7wNYvUITVMXU
+iUqwRCX2PIWb5XkaBi/cUXUo/4AY8950wiAk4is/7aKtcRgQim7vSwRrX6MKaWiM
+flj65B5/uyCQf4ZbVT6StMjPc40dfgL8deByMoY1o4KCEkci4p2x1w1o4QKBgAz5
+vAaWqpGbijJOpilQFNkoTPRt9MbUdf+RrW+RtfiStft3d4SvzqZ8z+WXzM/xySz5
+aCIvumxIaK58wc4DtHBPeCyRnvCV+WVZ0sth6/pHQg/UpOIUiJINV2Ih8GZxUVO4
+/ErPGS9pTEZ0ULhpc/Xo6qntfuPghVsJ5bmSVb8HAoGBAInwmcwiQ9u7hFBGqGhM
+DJnZswogDNQrDetfoCza6DCq2k2zNFKiGNnQ678rd6arY6o1nchxDnhxGDgNXNlh
+fnFkiwzZv3B5/I+gCDT0Ll+e8KSnSbXyMww0CgpCSNbcLWakZQL4COZjIgWU1c6t
+mhiMWuCs2aYVs/6FH7VRKLwh
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096.crt
new file mode 100644
index 00000000000..e03fba26e39
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096.crt
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIE+zCCAuOgAwIBAgIJAOeAAjUr7nFXMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
+BAMMCXNhbWwtdGVzdDAeFw0xODA0MjAxNDIwMThaFw00NTA5MDUxNDIwMThaMBQx
+EjAQBgNVBAMMCXNhbWwtdGVzdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAN4Mv8SsYGlzFuj30h7XwS2RX3VJ0oZ26l+lm1exDQTnlXumI51y6ezPKbPp
+Nn3q2hP7E4yJYyaA4Ai6LrDOa/J7wXo1F21J7Mq13XstVt+0tfMrkrtPxsF1dRKz
+NuIEEy9BWls+j+oXn5vZhUWuGDzLetKUBXJGcimhYlTCYcDITw2sLgBQXEqoQg7m
+uGPUTOCnkkj0/tBMKAW57/JwUM/PZCJG2HPAKSSimFW+1HweQSWtv4Ro2UIMQ1tB
+LCIk/eOA3jMIaWWycs6yWnOSm1bEBsJqT+dJoIssX80CjcjBMGWIXyuCRHx63Bvf
+4d/merh178Ru7r07CKeBG7ufj5jD0stE+0QBVgYhqHxn15u4cQ0gQiHJeINcW1H8
+jYOoMY7rBeLdPVOxwVhE9InQfdJxA+gLnmGkjEP6YjvD6ItABtyNBure54PMivLS
+LxWB9LEwe/cXeoueWQoav2fdz5rXRHUAOEn5xrPYssqIiPmKuLm7zxq+jQTbKauS
+pJD94xYWpe90cb1gnWQiux0VltPDpqpGWM67pESJpopcYmvXX/EJD/Pjfho9FkVY
+wEgb6mG6wVmp+8/Hy1TJMKjT38V1Svd4cR2wKn+9B/5c0j2BLou5kGSpIwV/vL1e
+4WyxxL5q9DKy9iFCTnXZT8nI7sfAA3sEt3cMtf/FnNkGnfmJAgMBAAGjUDBOMB0G
+A1UdDgQWBBRb5Dmqei4zerSbzPQQs8xI09WXQzAfBgNVHSMEGDAWgBRb5Dmqei4z
+erSbzPQQs8xI09WXQzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQB3
+zSgKv4f3lf68oqnVkbKfNS3xglwk8UK2kyhGd2yLz6Ohs/zGm86mA2LjuIJWrPTW
+7hHCxl8QfvsnU0+PVsCBpWIPH5yen0ZCYO0XhN2rsEi60NOVs9E8tzLXhP1Wqp0G
+y6qPQbznIgMyGqT6O4mbEIby9lGJTQ2W19CkKIQqZnbR59Ax8RQbV5XGMP4GP3fm
+Rd1U4w+2s/4wnl7Vz+P81iOTuTglz33H16GySaODI46uPd9Krgf0Grljmfs2osOd
+l+1cUqVJuQgf4I4Jvx6kACTk7RrTJ3vclWl+XFFaXM5NJWMlBKT1QxX/Xl/Fqt5o
+GtXCamKvdr4LdQNm26ZZnVNywFs8jPV/vsYhyzbujj5IOAKGML1Q3zs4+rlVLhes
+7rxnA36xd9KQ0O1b/SMQOvbjBQrLO84gNHFt165a6va0eiQEp70CwEFpOZQ/GRtK
+7EqDtqBQn2U9Kck9UitfXuebC4usgD3CfeQwqKYuGlwkgnuOWLv2m7gGQ500GJc/
+UkcEzwiTvETOyXynccegdFUwyd6+xm/BR0Lxm7mh/ELuM3eP20oRnStOs+1WWmhz
+wABfvaDwTHKE+aO9v049HZW6DoNVUg2ekWte1slDnuwCDqqz6imhZ2pOY6mzd4TG
+EnZBdRDwUJcsSnzKcn33d2rYmoE6PHsfpppNj4rxfQ==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096.key
new file mode 100644
index 00000000000..9e3331a2174
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096.key
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDeDL/ErGBpcxbo
+99Ie18EtkV91SdKGdupfpZtXsQ0E55V7piOdcunszymz6TZ96toT+xOMiWMmgOAI
+ui6wzmvye8F6NRdtSezKtd17LVbftLXzK5K7T8bBdXUSszbiBBMvQVpbPo/qF5+b
+2YVFrhg8y3rSlAVyRnIpoWJUwmHAyE8NrC4AUFxKqEIO5rhj1Ezgp5JI9P7QTCgF
+ue/ycFDPz2QiRthzwCkkophVvtR8HkElrb+EaNlCDENbQSwiJP3jgN4zCGllsnLO
+slpzkptWxAbCak/nSaCLLF/NAo3IwTBliF8rgkR8etwb3+Hf5nq4de/Ebu69Owin
+gRu7n4+Yw9LLRPtEAVYGIah8Z9ebuHENIEIhyXiDXFtR/I2DqDGO6wXi3T1TscFY
+RPSJ0H3ScQPoC55hpIxD+mI7w+iLQAbcjQbq3ueDzIry0i8VgfSxMHv3F3qLnlkK
+Gr9n3c+a10R1ADhJ+caz2LLKiIj5iri5u88avo0E2ymrkqSQ/eMWFqXvdHG9YJ1k
+IrsdFZbTw6aqRljOu6REiaaKXGJr11/xCQ/z434aPRZFWMBIG+phusFZqfvPx8tU
+yTCo09/FdUr3eHEdsCp/vQf+XNI9gS6LuZBkqSMFf7y9XuFsscS+avQysvYhQk51
+2U/JyO7HwAN7BLd3DLX/xZzZBp35iQIDAQABAoICAAgLIi83p05qktvhjkT7v82s
+xG51PCEO0bKhRx1IFpak5O9Tt1qOvRaM8o/H1Od+yGOM5spid6r/ZB4s0GArOhHQ
+ldOddLnKwb8eE2XQ4KK94xFp9KjAXQzI+nKw9z38s800atd/TqtGK8vzdzZs9gfN
+vyc9oWzgTGZhqDQ1zmCzYNm38Pql7pHtwmbTyL4lBJvmtg/agBh/ibubXqvDkcnV
+U2VCd7jJrzPah/YjMYNFfUqmHpfnTGduFkqJ89VQzbmeA26J0XeTnUELiOdC2kms
+VCpau4Y/Tod8FgRRIV2yUdR7uibTUzPHJ44C8CWyLaPc8dCFzDQinU+kB6MmRodK
+1v9+JO63BmZ/Vj/qOzzvkr2fhideQq9SBXYxSmPS9hMs0MGcltZaMo5wTkU4bikc
+gOQrh6pYuTQOFjqMf4+03v0SAFS0j6yByL7ZewrrD4MGyyAQIvbg5TSeTVHartkq
+7MsE5Cppy8rhbmdgGrTAwSe6RJuNRAFLawNvOSglTfHd7WTiiJloZLUQBJaRi+uf
+u96QUNbnNpLpLVnvLP0FjDoxgxBPe8k7D+1odLDIu3uwDui6VSvZwUh2SG7YJgkN
+ntrFcKh/E+gQN4lOUZimWdRjDgy8uyItDvA0SZuq+snVe+FKSU2PXVByKiz4oTBR
+dKhFM8iyd0mvdWvgKNF5AoIBAQD4XmKhuDV1M3JpKZ251oHqUzbk0zMzW0O4mKJA
+/ogpZtLENdoHLXeyRY7nXFk4RmZ/0j5LLUHrEsKv4pd0Uxdm5Pu8TF3KfCp+RYaP
+QAjNeUVnmPwgIkCc9cygviIaAeVmKpyRwi4cq0FzHwSZ/sRzOV2zrEyPTS/atrR8
+twgNICRwjhuxw9nHSz5KAvSu/h77zy1cpBHUbSVWWuPCJBgNkt/HiPaEDW4DuMdY
+dAyszRv9NCB/bhDG7hRHWQezaYn/b7aLzF+9YOFOJvKLUNxuiHS2YujJ2gAOpsph
+Z+27dh3vRgzS4kzlh61x/52E4+9BSmo8Bh7ND+/LphQmednXAoIBAQDk31hW3nZK
+BRTvaSr5lH44Qs2TqpOHcWetmNLOQkyoNh+x7VHNmjfC/34A/uZUIbA85M/hPc7O
+cXD6Be+AUDNQ+EKfZ6hfpa4fVfYMz/M+rhgSaeWxyddr62FUs2Ydckfn8HFgGXIi
+vxE2o24ZcwnM4rs0T+Zabls15udQ9SbC0GeiSmwH9wHmu+J6uZqw8ylHkqg+GOSU
+q5H2qf6J9/9nUine1KZmHZAYdWF9zpQi9D/3gKEzaDMmRMADy24qgOLbcmVXPvPk
+8Pag9SenyKlT8e0TvLYE02Iot1mESdZ17zaPVklxX/o/kRn7oH7HzKFuAtqqfj3o
+83i2H9Ft+hufAoIBAQC27WV9sNwGp06z78fQkRH8kS+UF43VXHmjYx/V+OI2hBnm
+E7eyo6VOMvcOpjC8RvXFXQcufXXYemfT/XMJZQ2OZkaWqDRIJ21wtSpnJYWWOKSK
+qd3AmRm3wT3mgkNBnnXj6qyImlk2GlhJPuY3ubHdH7pI1DVLMlF1qC2E0ZXnfO35
+zGDPa+1hYKTPBCBNJrORSUUiv2C2cXEXijfHzKe+j5esMc9G8VE/AoAoQMj5GNRt
+iFALKvjGW6Gp7wPB+5B9Bz2O94boR4uJ8RugynygGHbFwlGsIZj7MZNLbK1m7Zcc
+nR5iz/RM9cIkfVz5/JtCHlniPau/4uX9uyOKNyLfAoIBAQCklyGWRyFWFdV6Xm0z
+UuB6YUApw2+Y5asjolVnUzKBfXrJn9tGOnODXe0llinZsuhkwj/kwWgp+la+1unn
+osVko0R2Ejt5nVJc4pqxmBJbryNMiq9ObdLnnzw9h04WOwsO91DxRRtZdYJRgrI4
+xwvzNdJeyl7kBZy+ZLFQ/RvE2c7NXSvXhoDth4xVqYhfXF8BQ6yOC6TGbaPoeVO9
+sIURrnrB7rdDlFr929widx79DB28Rdqnd3XhPWvAztkI4+tA2UGbvn/y0n7qPaMo
+/BsZbU+K9BkJ22Ip2cEca2U5JrBb4DesutLiR90hocfKs5Qb4x2RonuvPPhAMR2R
+M14NAoIBAE88ccNxEPx1oXMqEFC/+AEhSPiLVkR58+IDFBqHPX29B+utb2X8u4pp
+CZ+vJ7ImI2miz3D5Vj5JALEoHJgUBK4XUiBH6NgTPiyJwD7eDoqqmpeob2f/VvBR
+ApPU0hCvEvts+eYsQSbN2I86LS4PlSy29J47ns1EI5B5uq0ZrFdBSSo5Gz79rI/V
+qKuVWmAaTy5aPtpOLMn5MvvDlFYVxrcSBaps+uJKclChw7EhlKuxXeSAuZPd4azZ
+rzKgsU+nLCBv751//dCY7e0bdMs6xsjPaFfXPV2bcKQngF+efo10BdglEDfP809c
+4NWTCBasDmK/cqNnP/Q5TDXbsL/AFPU=
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096_updated.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096_updated.crt
new file mode 100644
index 00000000000..03270afa3f7
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096_updated.crt
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIE+zCCAuOgAwIBAgIJAPN5+lbssaDbMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
+BAMMCXNhbWwtdGVzdDAeFw0xODA1MDQwNzQ3MzdaFw00NTA5MTkwNzQ3MzdaMBQx
+EjAQBgNVBAMMCXNhbWwtdGVzdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAMk0gXhWEXcsEcAZfyA59QSHPROP73zLNyL2IOLJL3bn2cScZir8EfRno6B4
+LGRKq71gFU7nT8Tn6bbUYhzqZEn/RzdNMqnTC0N4RgdU6/y2bPmc77DxNZHJGU/U
+PokB9JfO7ox+FYFg26c/5pyNofFa4/iUA2iDclivSUuWMlWN3HTPR1Nf2743RNYx
+dlgMr0xXB6AApYKvLtirjpx5BokxCIwH1QwJzGDIUKKQGvj/+7X8G5GQo+pOwhiY
+3oUtiHsxRRetZr/x+51dSD96A/GBmEe/BUqd+YZ5CJSwAPwoz8OsznQjQZWHV+Qy
+sgpoF2jPTc2klryzEk/sQkJxH3nNW6jY0Bt3oqTTtt3VZLSgMI1vjK5d5sK7s5NW
+vOTtJZoOVCJwzNIPuZlN0rKuI9w9V9KpuPY6mS3xx7hssYJKBRoFEP9hyv9wz+C9
+KZVCfbafPnxxbdU1grR7FkZwop8H/shU/+61g3GXrZ8fnPtnhsM3NgZsr26dyeQk
+ax+r/dg5QEW7ZWmDLmRvuahdSAUJHrnEGTncpz3s3EGDSPROVOCBHLWyyWAtl1lV
+9OnZfjQCaKPm9n5pUBXykOYc8sO7N+Ds92CDJwm9RM+TGY6K+j34mSZ+0Cc9MNEE
+15eWboZyYavZG1OD0G/e5VgV9pzrRWnNe17Jj4w8xB0Yd4Z1AgMBAAGjUDBOMB0G
+A1UdDgQWBBQi3Kx6SrWWgbFC1uzD0lrKOR74MDAfBgNVHSMEGDAWgBQi3Kx6SrWW
+gbFC1uzD0lrKOR74MDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCi
+GEv9PZOIPxfJtaQQb04XmfLyUX96oqAnxhuERpioVKT7oan/67VSm5UMaZyjx0Nm
+sDQRo5K50QgCXvIta0EZeHfpDCldJxaXsJ0nvRf4jTm2BgZRHCXI3M6K6Na+lZwp
+XOofJCaWrfU8zh1bfSgMhFMf61X7hAxsc88bGHxDEbO6pYh4yyBjNQ8K7XzJlJfE
+f0tLiLHDET6Jfonz0OXfLhdryRBe7F41UVkp4WQCCem3dv5uNaNyJ0XENIUMd0ua
+rOMjm0lPvuo1kmxF5ptMTtuBuoTVcbHP2of/ZU0u5QNMgyRsqo8RvB59qpxz7Cdt
+HbEXHKuut64pjx0N43WrwrxgXF24b3apItPnsz1nypntS6hMwC/AULN0bM6Puon4
+V+Ctd9GntkCaw8b3LaCxQgf+Fhpp1tIWfiLFb/O4jHQVXAz90tkeimAQwwJodcCZ
+X+9+aeJJOeqZ2U2f48D55tWkwkkSsVZd9otr80L7fT/7zcsXIsMASntclT/JZqHa
+eWzZbHgxsP2jPei/AHJlAdPDTRAlgTFNn01rOYoequ9+851f++d/C4bDsARU9Uuv
+5ETdDj3VwuRrtrOx4T1cduTbUv1TbA1ypSwupcnSFnkKrZbZUZqjCIZufWVXdpqi
+48qykDhPKVvXMRIW3XPHEMsg1fBj+x5qOByh8AMbwg==
+-----END CERTIFICATE-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096_updated.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096_updated.key
new file mode 100644
index 00000000000..56705e749a2
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/saml_RSA_4096_updated.key
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDJNIF4VhF3LBHA
+GX8gOfUEhz0Tj+98yzci9iDiyS9259nEnGYq/BH0Z6OgeCxkSqu9YBVO50/E5+m2
+1GIc6mRJ/0c3TTKp0wtDeEYHVOv8tmz5nO+w8TWRyRlP1D6JAfSXzu6MfhWBYNun
+P+acjaHxWuP4lANog3JYr0lLljJVjdx0z0dTX9u+N0TWMXZYDK9MVwegAKWCry7Y
+q46ceQaJMQiMB9UMCcxgyFCikBr4//u1/BuRkKPqTsIYmN6FLYh7MUUXrWa/8fud
+XUg/egPxgZhHvwVKnfmGeQiUsAD8KM/DrM50I0GVh1fkMrIKaBdoz03NpJa8sxJP
+7EJCcR95zVuo2NAbd6Kk07bd1WS0oDCNb4yuXebCu7OTVrzk7SWaDlQicMzSD7mZ
+TdKyriPcPVfSqbj2Opkt8ce4bLGCSgUaBRD/Ycr/cM/gvSmVQn22nz58cW3VNYK0
+exZGcKKfB/7IVP/utYNxl62fH5z7Z4bDNzYGbK9uncnkJGsfq/3YOUBFu2Vpgy5k
+b7moXUgFCR65xBk53Kc97NxBg0j0TlTggRy1sslgLZdZVfTp2X40Amij5vZ+aVAV
+8pDmHPLDuzfg7PdggycJvUTPkxmOivo9+JkmftAnPTDRBNeXlm6GcmGr2RtTg9Bv
+3uVYFfac60VpzXteyY+MPMQdGHeGdQIDAQABAoICAFnSZ84Z1jg2Y0I336m6VeiM
+mzaFditm6RlheXLkz5ysimocS/v6heVu8vwrSd4H+71SDJEp8FF+Grb0/0vbU6Q5
+I0jL3Mc1oPygz9psDeHGasXQSqzaMckAVp1tqfEt/0xaI+JyUxVr8QMsIr5W+Cmw
+Ir+RDCh3Le/raLQmvBe3eehntHbC/21ebQuWDzflichxvcSvJTQ/EpHFnKe727AZ
+RLCGupRiN2wpYN4BqRjp5ivq/T+xq4tpV3r1m7kmh5w/dZHJZmpgE6y/vQYhaWtC
+KII3A5y5A3EFzU/bdsUbTw0SsyPjrV6cih8khpjguTqf+SLJzEU3SACH/1h7+cly
+utKPubBSXvMe5eo+uCN8VD3/lX1k9Ljz0ZJxEadeqXQqp94G1T3ItSWkgGzGy/HH
+uzOfQWPP9Xy69dW2ojWLe5mYidQpz6Zq6soOBybeaJHjGNTxnyEaWGn7KdEirRLR
+n0GM3IJC9VdvNRSQOfGKwjxb6rVda0O4PERaXUTaBVan7t/BtZF6NzXJL47YugV4
+k8NonfGgZ6mmhQfQfrrpTnZIyRK9SaO7jhUWcnqVSa4DZKJI58UuUL0VJIzweGa/
+b5m7Se4DmRGTVywsi6uN+zjJ0x739EBjoDcNZQumO/+e/lGf54qVU3pPxdfAFHFv
+5jcKUBcWzAFRanRXu15tAoIBAQDmtEUmPoas4TGeaz1k7eReIm38yV35U2xm78fn
+yyh1J/HTrWzOXlogouO6n6BJ4ce1l1YZH0C+pUGPEn2UHxwUILpGbuKdNxT/aUvl
+qwraAe3bOu3c7hR/pQ7KL3VrSj0VjtDfOzAMPkzzyVm2dmfIE51/WBQn72k35kQy
+BhgvMpUUNJflHri9xV6c04GOinGu4hpuPOUonguOvRqFQxL2Q9lAkj2BTRgsxd+b
+nBe4N/0dBG/1zmCKUIE226lTFUllFhuPi977xLZgs7QAnouvEojtUSgXG90V0bKk
+PjXf7mVZ2oQ9MIDQeK/lEd16aYqAb8RGi5asxk+auEFWJWOXAoIBAQDfRDbC4qQl
+11sYKozgnmoWo8xXh05yS2mlfzNnjvQAohAtvGCc6qlEYn2GefHbZrGvEyLqqh1a
+V17OVBk3KRdHcYLx4yUyg9TKV9Q/BeMg8Hjjs0Ql80pukx7JXBl1Sp1NHQhAFiU1
+JtjXr/uec5Z6XD0bEwoGGCH/XXJNFVl2zqs7m3rfJVVua4i0GIr1RKO39NrMH4dx
+E/wtU1Nt3HrxIvF4mWsyQssV/HnxKThnC3kHOx2SexM4tpfpGP74JCHvqnZwxO3D
+IyzQZu/Ok8Firxiwa+xaZL1yB8dPH9xXoHq9dUFm+CUlBdXOF471/WRHnCRPg0KY
+tkz97Hue5zfTAoIBAEd6WOZVfwJ3LxlnHnlz30pvHmawuQXzm+V0qxoc7qcFvj4Y
+QFrcDs6HyUjcBhx98JNJlSppbXTj3KEIWJIY5WkzDqOd3WZaV44ewJ4i1VTgPiKr
+amEF/qHhsOhhtd6M/Mn+GqbfPq68arkpjDslCliKA0UeM/h/i7j/Bef9zWZqJJhD
+B0C8uP5K9VpfiYdxS3Gkqg23nkRsWyZZXqslMe3M7bW82YODMFdG41XiEdNIvYpN
+AqdEztJryO0HN7n/IWNJazaZXnfg5aSmaMG8XYjblEL63xHx1xjYhKGwiJ6dzRb+
+xfPzYCW3DsBJPbacloXemxBEVWWod6d3KP8YzHcCggEAQCpnnpzqViHNgWWBNXDx
+xm3u5Vzys7BuvWyQRnv0LlZlVe+kyJQ8b3Xq44Iae1bJTCqwx0Z6xyMDEUNkN9Es
+apD59DC22QzAVCLn0fEMNMRHyhEUTd/dDWhk2bQJcQcvrCDi5SA4M01l1p8yLnjD
+z4jA2w4evF+lLbIajoLLQnTlC22E46rkIabwE+pVzWWbs9vAIhgRofL/b7tZ5+IM
+x06mnWViRICjwz7bgO660gqfDu/zcMzEWnFHuWtAo+omgq23+nLubj2mvIJI+1LF
+qmnuK43o0JXRSHtp0Zizh8+MVvTjBgfdDQXfS6rDoHjhoB8E5IEx25fRCs0zPhjv
+lwKCAQEA1I4jjP3M6GUELGqknXCkF1BEwKCV8fL3DuiXWR3YuImMmUU+PYM5T9J/
+AdJWLUyMLdHjqNiCR/p0JAU+H1B+VQcngbs96bF5grfX1IhX0fbeEODuUJNJ2ET5
+QoBcXR0FORDq4L/ai8mBlIb1gUWuIj47C5XvNLHP8FOovkMwrCXkRVq5FL5YPG8j
+U0FnVfyDttD/rIZB01bjuJtsirt+9tu7bFwwxWGFrK3MUWPsqN8F1NudxybSWftb
+0VXenj36chDpqIg+Ud06KI2U1B1escMhr/ZVFaAjL7GeDtFCriOYx+dDk9HFMzKT
+IPb72BK1dZcWIARIHV9sIrN/bjyfwg==
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/test_ec.key b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/test_ec.key
new file mode 100644
index 00000000000..7836ec59794
--- /dev/null
+++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/authc/saml/test_ec.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDA1PGx0jyHMArH0IJAj
+dlH1LXhGOiJlpXzaYRIYza5/EDEq7CAv9MHxGPj1a15ebpOhZANiAARIKithDtFG
+4uQH/+g3y1ieu+00fkM4gI7iHCLdcSUm+mEjCC3SPixvO2KSHiZbUQ5UKuj8iWZI
+5Mv8oN3b4ymhdhyTmmK7/Lfi4aoU5GjhFuA7qIzl2T58rKilsVpNmPY=
+-----END PRIVATE KEY-----
diff --git a/x-pack/plugin/sql/sql-proto/licenses/lucene-core-7.4.0-snapshot-1cbadda4d3.jar.sha1 b/x-pack/plugin/sql/sql-proto/licenses/lucene-core-7.4.0-snapshot-1cbadda4d3.jar.sha1
new file mode 100644
index 00000000000..cea13d14fe1
--- /dev/null
+++ b/x-pack/plugin/sql/sql-proto/licenses/lucene-core-7.4.0-snapshot-1cbadda4d3.jar.sha1
@@ -0,0 +1 @@
+f345b6aa3c550dafc63de3e5a5c404691e782336
\ No newline at end of file
diff --git a/x-pack/plugin/sql/sql-proto/licenses/lucene-core-7.4.0-snapshot-cc2ee23050.jar.sha1 b/x-pack/plugin/sql/sql-proto/licenses/lucene-core-7.4.0-snapshot-cc2ee23050.jar.sha1
deleted file mode 100644
index 4aecfc6a550..00000000000
--- a/x-pack/plugin/sql/sql-proto/licenses/lucene-core-7.4.0-snapshot-cc2ee23050.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e118e4d05070378516b9055184b74498ba528dee
\ No newline at end of file
diff --git a/x-pack/qa/saml-idp-tests/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticationIT.java b/x-pack/qa/saml-idp-tests/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticationIT.java
index 67d338ab2db..bf4ad79c59d 100644
--- a/x-pack/qa/saml-idp-tests/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticationIT.java
+++ b/x-pack/qa/saml-idp-tests/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlAuthenticationIT.java
@@ -54,7 +54,7 @@ import org.elasticsearch.mocksocket.MockHttpServer;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.xpack.core.common.socket.SocketAccess;
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
-import org.elasticsearch.xpack.core.ssl.CertUtils;
+import org.elasticsearch.xpack.core.ssl.CertParsingUtils;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.AfterClass;
@@ -553,8 +553,8 @@ public class SamlAuthenticationIT extends ESRestTestCase {
private SSLContext getClientSslContext() throws Exception {
final Path pem = getDataPath("/ca.crt");
- final Certificate[] certificates = CertUtils.readCertificates(Collections.singletonList(pem));
- final X509ExtendedTrustManager trustManager = CertUtils.trustManager(certificates);
+ final Certificate[] certificates = CertParsingUtils.readCertificates(Collections.singletonList(pem));
+ final X509ExtendedTrustManager trustManager = CertParsingUtils.trustManager(certificates);
SSLContext context = SSLContext.getInstance("TLS");
context.init(new KeyManager[0], new TrustManager[] { trustManager }, new SecureRandom());
return context;
diff --git a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateToolTests.java b/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateToolTests.java
index e6685e9c6cb..834a54bb5f4 100644
--- a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateToolTests.java
+++ b/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateGenerateToolTests.java
@@ -87,6 +87,7 @@ import static org.hamcrest.Matchers.notNullValue;
public class CertificateGenerateToolTests extends ESTestCase {
private FileSystem jimfs;
+ private static final String CN_OID = "2.5.4.3";
private Path initTempDir() throws Exception {
Configuration conf = Configuration.unix().toBuilder().setAttributeViews("posix").build();
@@ -264,8 +265,8 @@ public class CertificateGenerateToolTests extends ESTestCase {
final int keysize = randomFrom(1024, 2048);
final int days = randomIntBetween(1, 1024);
- KeyPair keyPair = CertUtils.generateKeyPair(keysize);
- X509Certificate caCert = CertUtils.generateCACertificate(new X500Principal("CN=test ca"), keyPair, days);
+ KeyPair keyPair = CertGenUtils.generateKeyPair(keysize);
+ X509Certificate caCert = CertGenUtils.generateCACertificate(new X500Principal("CN=test ca"), keyPair, days);
final boolean generatedCa = randomBoolean();
final char[] keyPassword = randomBoolean() ? SecuritySettingsSourceField.TEST_PASSWORD.toCharArray() : null;
@@ -288,8 +289,8 @@ public class CertificateGenerateToolTests extends ESTestCase {
assertTrue(Files.exists(zipRoot.resolve("ca").resolve("ca.crt")));
assertTrue(Files.exists(zipRoot.resolve("ca").resolve("ca.key")));
// check the CA cert
- try (Reader reader = Files.newBufferedReader(zipRoot.resolve("ca").resolve("ca.crt"))) {
- X509Certificate parsedCaCert = readX509Certificate(reader);
+ try (InputStream input = Files.newInputStream(zipRoot.resolve("ca").resolve("ca.crt"))) {
+ X509Certificate parsedCaCert = readX509Certificate(input);
assertThat(parsedCaCert.getSubjectX500Principal().getName(), containsString("test ca"));
assertEquals(caCert, parsedCaCert);
long daysBetween = ChronoUnit.DAYS.between(caCert.getNotBefore().toInstant(), caCert.getNotAfter().toInstant());
@@ -308,11 +309,9 @@ public class CertificateGenerateToolTests extends ESTestCase {
}
}
- try (Reader reader = Files.newBufferedReader(zipRoot.resolve("ca").resolve("ca.key"))) {
- PrivateKey privateKey = CertUtils.readPrivateKey(reader, () -> keyPassword != null ?
+ PrivateKey privateKey = PemUtils.readPrivateKey(zipRoot.resolve("ca").resolve("ca.key"), () -> keyPassword != null ?
SecuritySettingsSourceField.TEST_PASSWORD.toCharArray() : null);
- assertEquals(caInfo.privateKey, privateKey);
- }
+ assertEquals(caInfo.privateKey, privateKey);
} else {
assertFalse(Files.exists(zipRoot.resolve("ca")));
}
@@ -324,8 +323,8 @@ public class CertificateGenerateToolTests extends ESTestCase {
assertTrue(Files.exists(cert));
assertTrue(Files.exists(zipRoot.resolve(filename + "/" + filename + ".key")));
final Path p12 = zipRoot.resolve(filename + "/" + filename + ".p12");
- try (Reader reader = Files.newBufferedReader(cert)) {
- X509Certificate certificate = readX509Certificate(reader);
+ try (InputStream input = Files.newInputStream(cert)) {
+ X509Certificate certificate = readX509Certificate(input);
assertEquals(certInfo.name.x500Principal.toString(), certificate.getSubjectX500Principal().getName());
final int sanCount = certInfo.ipAddresses.size() + certInfo.dnsNames.size() + certInfo.commonNames.size();
if (sanCount == 0) {
@@ -459,9 +458,8 @@ public class CertificateGenerateToolTests extends ESTestCase {
}
}
- private X509Certificate readX509Certificate(Reader reader) throws Exception {
- List list = new ArrayList<>(1);
- CertUtils.readCertificates(reader, list, CertificateFactory.getInstance("X.509"));
+ private X509Certificate readX509Certificate(InputStream input) throws Exception {
+ List list = CertParsingUtils.readCertificates(input);
assertEquals(1, list.size());
assertThat(list.get(0), instanceOf(X509Certificate.class));
return (X509Certificate) list.get(0);
@@ -484,7 +482,7 @@ public class CertificateGenerateToolTests extends ESTestCase {
ASN1Sequence seq = ASN1Sequence.getInstance(generalName.getName());
assertThat(seq.size(), equalTo(2));
assertThat(seq.getObjectAt(0), instanceOf(ASN1ObjectIdentifier.class));
- assertThat(seq.getObjectAt(0).toString(), equalTo(CertUtils.CN_OID));
+ assertThat(seq.getObjectAt(0).toString(), equalTo(CN_OID));
assertThat(seq.getObjectAt(1), instanceOf(DERTaggedObject.class));
DERTaggedObject taggedName = (DERTaggedObject) seq.getObjectAt(1);
assertThat(taggedName.getTagNo(), equalTo(0));
diff --git a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateToolTests.java b/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateToolTests.java
index cad254207a6..3cc6c73b3af 100644
--- a/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateToolTests.java
+++ b/x-pack/qa/security-tools-tests/src/test/java/org/elasticsearch/xpack/core/ssl/CertificateToolTests.java
@@ -54,6 +54,7 @@ import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.security.auth.x500.X500Principal;
import java.io.IOException;
+import java.io.InputStream;
import java.io.Reader;
import java.net.InetAddress;
import java.net.URI;
@@ -98,6 +99,7 @@ import static org.hamcrest.Matchers.nullValue;
public class CertificateToolTests extends ESTestCase {
private FileSystem jimfs;
+ private static final String CN_OID = "2.5.4.3";
private Path initTempDir() throws Exception {
Configuration conf = Configuration.unix().toBuilder().setAttributeViews("posix").build();
@@ -290,8 +292,8 @@ public class CertificateToolTests extends ESTestCase {
int keySize = randomFrom(1024, 2048);
int days = randomIntBetween(1, 1024);
- KeyPair keyPair = CertUtils.generateKeyPair(keySize);
- X509Certificate caCert = CertUtils.generateCACertificate(new X500Principal("CN=test ca"), keyPair, days);
+ KeyPair keyPair = CertGenUtils.generateKeyPair(keySize);
+ X509Certificate caCert = CertGenUtils.generateCACertificate(new X500Principal("CN=test ca"), keyPair, days);
final boolean generatedCa = randomBoolean();
final boolean keepCaKey = generatedCa && randomBoolean();
@@ -325,8 +327,8 @@ public class CertificateToolTests extends ESTestCase {
assertTrue(Files.exists(zipRoot.resolve("ca")));
assertTrue(Files.exists(zipRoot.resolve("ca").resolve("ca.crt")));
// check the CA cert
- try (Reader reader = Files.newBufferedReader(zipRoot.resolve("ca").resolve("ca.crt"))) {
- X509Certificate parsedCaCert = readX509Certificate(reader);
+ try (InputStream input = Files.newInputStream(zipRoot.resolve("ca").resolve("ca.crt"))) {
+ X509Certificate parsedCaCert = readX509Certificate(input);
assertThat(parsedCaCert.getSubjectX500Principal().getName(), containsString("test ca"));
assertEquals(caCert, parsedCaCert);
long daysBetween = getDurationInDays(caCert);
@@ -347,10 +349,9 @@ public class CertificateToolTests extends ESTestCase {
}
}
- try (Reader reader = Files.newBufferedReader(zipRoot.resolve("ca").resolve("ca.key"))) {
- PrivateKey privateKey = CertUtils.readPrivateKey(reader, () -> keyPassword != null ? keyPassword.toCharArray() : null);
- assertEquals(caInfo.certAndKey.key, privateKey);
- }
+ PrivateKey privateKey = PemUtils.readPrivateKey(zipRoot.resolve("ca").resolve("ca.key"),
+ () -> keyPassword != null ? keyPassword.toCharArray() : null);
+ assertEquals(caInfo.certAndKey.key, privateKey);
}
} else {
assertFalse(Files.exists(zipRoot.resolve("ca")));
@@ -363,8 +364,8 @@ public class CertificateToolTests extends ESTestCase {
assertTrue(Files.exists(cert));
assertTrue(Files.exists(zipRoot.resolve(filename + "/" + filename + ".key")));
final Path p12 = zipRoot.resolve(filename + "/" + filename + ".p12");
- try (Reader reader = Files.newBufferedReader(cert)) {
- X509Certificate certificate = readX509Certificate(reader);
+ try (InputStream input = Files.newInputStream(cert)) {
+ X509Certificate certificate = readX509Certificate(input);
assertEquals(certInfo.name.x500Principal.toString(), certificate.getSubjectX500Principal().getName());
final int sanCount = certInfo.ipAddresses.size() + certInfo.dnsNames.size() + certInfo.commonNames.size();
if (sanCount == 0) {
@@ -607,9 +608,9 @@ public class CertificateToolTests extends ESTestCase {
assertThat(node3File, TestMatchers.pathExists(node3File));
- final KeyStore node1KeyStore = CertUtils.readKeyStore(node1File, "PKCS12", node1Password.toCharArray());
- final KeyStore node2KeyStore = CertUtils.readKeyStore(node2File, "PKCS12", node2Password.toCharArray());
- final KeyStore node3KeyStore = CertUtils.readKeyStore(node3File, "PKCS12", node3Password.toCharArray());
+ final KeyStore node1KeyStore = CertParsingUtils.readKeyStore(node1File, "PKCS12", node1Password.toCharArray());
+ final KeyStore node2KeyStore = CertParsingUtils.readKeyStore(node2File, "PKCS12", node2Password.toCharArray());
+ final KeyStore node3KeyStore = CertParsingUtils.readKeyStore(node3File, "PKCS12", node3Password.toCharArray());
checkTrust(node1KeyStore, node1Password.toCharArray(), node1KeyStore, true);
checkTrust(node1KeyStore, node1Password.toCharArray(), node2KeyStore, true);
@@ -715,11 +716,11 @@ public class CertificateToolTests extends ESTestCase {
final Path node2Key = zip2Root.resolve("node02/node02.key");
assertThat(node2Key, TestMatchers.pathExists(node2Key));
- final KeyStore node1KeyStore = CertUtils.readKeyStore(node1P12, "PKCS12", node1Password.toCharArray());
+ final KeyStore node1KeyStore = CertParsingUtils.readKeyStore(node1P12, "PKCS12", node1Password.toCharArray());
final KeyStore node1TrustStore = node1KeyStore;
- final KeyStore node2KeyStore = CertUtils.getKeyStoreFromPEM(node2Cert, node2Key, new char[0]);
- final KeyStore node2TrustStore = CertUtils.readKeyStore(caP12, "PKCS12", caPassword.toCharArray());
+ final KeyStore node2KeyStore = CertParsingUtils.getKeyStoreFromPEM(node2Cert, node2Key, new char[0]);
+ final KeyStore node2TrustStore = CertParsingUtils.readKeyStore(caP12, "PKCS12", caPassword.toCharArray());
checkTrust(node1KeyStore, node1Password.toCharArray(), node2TrustStore, true);
checkTrust(node2KeyStore, new char[0], node1TrustStore, true);
@@ -782,8 +783,9 @@ public class CertificateToolTests extends ESTestCase {
* Checks whether there are keys in {@code keyStore} that are trusted by {@code trustStore}.
*/
private void checkTrust(KeyStore keyStore, char[] keyPassword, KeyStore trustStore, boolean trust) throws Exception {
- final X509ExtendedKeyManager keyManager = CertUtils.keyManager(keyStore, keyPassword, KeyManagerFactory.getDefaultAlgorithm());
- final X509ExtendedTrustManager trustManager = CertUtils.trustManager(trustStore, TrustManagerFactory.getDefaultAlgorithm());
+ final X509ExtendedKeyManager keyManager = CertParsingUtils.keyManager(keyStore, keyPassword,
+ KeyManagerFactory.getDefaultAlgorithm());
+ final X509ExtendedTrustManager trustManager = CertParsingUtils.trustManager(trustStore, TrustManagerFactory.getDefaultAlgorithm());
final X509Certificate[] node1CertificateIssuers = trustManager.getAcceptedIssuers();
final Principal[] trustedPrincipals = new Principal[node1CertificateIssuers.length];
@@ -808,9 +810,8 @@ public class CertificateToolTests extends ESTestCase {
}
}
- private X509Certificate readX509Certificate(Reader reader) throws Exception {
- List list = new ArrayList<>(1);
- CertUtils.readCertificates(reader, list, CertificateFactory.getInstance("X.509"));
+ private X509Certificate readX509Certificate(InputStream input) throws Exception {
+ List list = CertParsingUtils.readCertificates(input);
assertEquals(1, list.size());
assertThat(list.get(0), instanceOf(X509Certificate.class));
return (X509Certificate) list.get(0);
@@ -833,7 +834,7 @@ public class CertificateToolTests extends ESTestCase {
ASN1Sequence seq = ASN1Sequence.getInstance(generalName.getName());
assertThat(seq.size(), equalTo(2));
assertThat(seq.getObjectAt(0), instanceOf(ASN1ObjectIdentifier.class));
- assertThat(seq.getObjectAt(0).toString(), equalTo(CertUtils.CN_OID));
+ assertThat(seq.getObjectAt(0).toString(), equalTo(CN_OID));
assertThat(seq.getObjectAt(1), instanceOf(ASN1TaggedObject.class));
ASN1TaggedObject tagged = (ASN1TaggedObject) seq.getObjectAt(1);
assertThat(tagged.getObject(), instanceOf(ASN1String.class));
diff --git a/x-pack/qa/vagrant/src/test/resources/packaging/tests/10_basic.bats b/x-pack/qa/vagrant/src/test/resources/packaging/tests/10_basic.bats
index 898fedbff79..b3683b5dd15 100644
--- a/x-pack/qa/vagrant/src/test/resources/packaging/tests/10_basic.bats
+++ b/x-pack/qa/vagrant/src/test/resources/packaging/tests/10_basic.bats
@@ -30,6 +30,7 @@ setup() {
# Install the archive
install_archive
+ set_debug_logging
}
@test "[X-PACK] verify x-pack installation" {
diff --git a/x-pack/qa/vagrant/src/test/resources/packaging/tests/bootstrap_password.bash b/x-pack/qa/vagrant/src/test/resources/packaging/tests/bootstrap_password.bash
index 043a8911ac4..587b782541d 100644
--- a/x-pack/qa/vagrant/src/test/resources/packaging/tests/bootstrap_password.bash
+++ b/x-pack/qa/vagrant/src/test/resources/packaging/tests/bootstrap_password.bash
@@ -13,6 +13,7 @@ setup() {
export PACKAGE_NAME="elasticsearch"
clean_before_test
install
+ set_debug_logging
generate_trial_license
verify_xpack_installation
diff --git a/x-pack/qa/vagrant/src/test/resources/packaging/tests/certgen.bash b/x-pack/qa/vagrant/src/test/resources/packaging/tests/certgen.bash
index d75f75b383a..21e4284b215 100644
--- a/x-pack/qa/vagrant/src/test/resources/packaging/tests/certgen.bash
+++ b/x-pack/qa/vagrant/src/test/resources/packaging/tests/certgen.bash
@@ -96,6 +96,7 @@ install_node_using_archive() {
export_elasticsearch_paths
install_archive
+ set_debug_logging
verify_archive_installation
export ESPLUGIN_COMMAND_USER=$DEFAULT_ARCHIVE_USER
@@ -123,6 +124,7 @@ install_node_using_package() {
export_elasticsearch_paths
install_package
+ set_debug_logging
verify_package_installation
export ESPLUGIN_COMMAND_USER=$DEFAULT_PACKAGE_USER
diff --git a/x-pack/qa/vagrant/src/test/resources/packaging/tests/setup_passwords.bash b/x-pack/qa/vagrant/src/test/resources/packaging/tests/setup_passwords.bash
index c13a2951136..c33947c1ac9 100644
--- a/x-pack/qa/vagrant/src/test/resources/packaging/tests/setup_passwords.bash
+++ b/x-pack/qa/vagrant/src/test/resources/packaging/tests/setup_passwords.bash
@@ -14,6 +14,7 @@ setup() {
export PACKAGE_NAME="elasticsearch"
clean_before_test
install
+ set_debug_logging
generate_trial_license
verify_xpack_installation