Merge branch 'master' into index-lifecycle
This commit is contained in:
commit
a03241d590
|
@ -497,10 +497,15 @@ class BuildPlugin implements Plugin<Project> {
|
|||
project.afterEvaluate {
|
||||
project.tasks.withType(JavaCompile) {
|
||||
final JavaVersion targetCompatibilityVersion = JavaVersion.toVersion(it.targetCompatibility)
|
||||
// we fork because compiling lots of different classes in a shared jvm can eventually trigger GC overhead limitations
|
||||
options.fork = true
|
||||
options.forkOptions.javaHome = new File(project.compilerJavaHome)
|
||||
options.forkOptions.memoryMaximumSize = "512m"
|
||||
final compilerJavaHomeFile = new File(project.compilerJavaHome)
|
||||
// we only fork if the Gradle JDK is not the same as the compiler JDK
|
||||
if (compilerJavaHomeFile.canonicalPath == Jvm.current().javaHome.canonicalPath) {
|
||||
options.fork = false
|
||||
} else {
|
||||
options.fork = true
|
||||
options.forkOptions.javaHome = compilerJavaHomeFile
|
||||
options.forkOptions.memoryMaximumSize = "512m"
|
||||
}
|
||||
if (targetCompatibilityVersion == JavaVersion.VERSION_1_8) {
|
||||
// compile with compact 3 profile by default
|
||||
// NOTE: this is just a compile time check: does not replace testing with a compact3 JRE
|
||||
|
|
|
@ -210,7 +210,9 @@ public class RestClient implements Closeable {
|
|||
* @throws IOException in case of a problem or the connection was aborted
|
||||
* @throws ClientProtocolException in case of an http protocol error
|
||||
* @throws ResponseException in case Elasticsearch responded with a status code that indicated an error
|
||||
* @deprecated prefer {@link #performRequest(Request)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Response performRequest(String method, String endpoint, Header... headers) throws IOException {
|
||||
Request request = new Request(method, endpoint);
|
||||
request.setHeaders(headers);
|
||||
|
@ -229,7 +231,9 @@ public class RestClient implements Closeable {
|
|||
* @throws IOException in case of a problem or the connection was aborted
|
||||
* @throws ClientProtocolException in case of an http protocol error
|
||||
* @throws ResponseException in case Elasticsearch responded with a status code that indicated an error
|
||||
* @deprecated prefer {@link #performRequest(Request)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Response performRequest(String method, String endpoint, Map<String, String> params, Header... headers) throws IOException {
|
||||
Request request = new Request(method, endpoint);
|
||||
addParameters(request, params);
|
||||
|
@ -252,7 +256,9 @@ public class RestClient implements Closeable {
|
|||
* @throws IOException in case of a problem or the connection was aborted
|
||||
* @throws ClientProtocolException in case of an http protocol error
|
||||
* @throws ResponseException in case Elasticsearch responded with a status code that indicated an error
|
||||
* @deprecated prefer {@link #performRequest(Request)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Response performRequest(String method, String endpoint, Map<String, String> params,
|
||||
HttpEntity entity, Header... headers) throws IOException {
|
||||
Request request = new Request(method, endpoint);
|
||||
|
@ -289,7 +295,9 @@ public class RestClient implements Closeable {
|
|||
* @throws IOException in case of a problem or the connection was aborted
|
||||
* @throws ClientProtocolException in case of an http protocol error
|
||||
* @throws ResponseException in case Elasticsearch responded with a status code that indicated an error
|
||||
* @deprecated prefer {@link #performRequest(Request)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Response performRequest(String method, String endpoint, Map<String, String> params,
|
||||
HttpEntity entity, HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory,
|
||||
Header... headers) throws IOException {
|
||||
|
@ -310,7 +318,9 @@ public class RestClient implements Closeable {
|
|||
* @param endpoint the path of the request (without host and port)
|
||||
* @param responseListener the {@link ResponseListener} to notify when the request is completed or fails
|
||||
* @param headers the optional request headers
|
||||
* @deprecated prefer {@link #performRequestAsync(Request, ResponseListener)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void performRequestAsync(String method, String endpoint, ResponseListener responseListener, Header... headers) {
|
||||
Request request;
|
||||
try {
|
||||
|
@ -333,7 +343,9 @@ public class RestClient implements Closeable {
|
|||
* @param params the query_string parameters
|
||||
* @param responseListener the {@link ResponseListener} to notify when the request is completed or fails
|
||||
* @param headers the optional request headers
|
||||
* @deprecated prefer {@link #performRequestAsync(Request, ResponseListener)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void performRequestAsync(String method, String endpoint, Map<String, String> params,
|
||||
ResponseListener responseListener, Header... headers) {
|
||||
Request request;
|
||||
|
@ -361,7 +373,9 @@ public class RestClient implements Closeable {
|
|||
* @param entity the body of the request, null if not applicable
|
||||
* @param responseListener the {@link ResponseListener} to notify when the request is completed or fails
|
||||
* @param headers the optional request headers
|
||||
* @deprecated prefer {@link #performRequestAsync(Request, ResponseListener)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void performRequestAsync(String method, String endpoint, Map<String, String> params,
|
||||
HttpEntity entity, ResponseListener responseListener, Header... headers) {
|
||||
Request request;
|
||||
|
@ -394,7 +408,9 @@ public class RestClient implements Closeable {
|
|||
* connection on the client side.
|
||||
* @param responseListener the {@link ResponseListener} to notify when the request is completed or fails
|
||||
* @param headers the optional request headers
|
||||
* @deprecated prefer {@link #performRequestAsync(Request, ResponseListener)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void performRequestAsync(String method, String endpoint, Map<String, String> params,
|
||||
HttpEntity entity, HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory,
|
||||
ResponseListener responseListener, Header... headers) {
|
||||
|
|
|
@ -43,7 +43,6 @@ public final class RestClientBuilder {
|
|||
public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 1000;
|
||||
public static final int DEFAULT_SOCKET_TIMEOUT_MILLIS = 30000;
|
||||
public static final int DEFAULT_MAX_RETRY_TIMEOUT_MILLIS = DEFAULT_SOCKET_TIMEOUT_MILLIS;
|
||||
public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT_MILLIS = 500;
|
||||
public static final int DEFAULT_MAX_CONN_PER_ROUTE = 10;
|
||||
public static final int DEFAULT_MAX_CONN_TOTAL = 30;
|
||||
|
||||
|
@ -196,8 +195,7 @@ public final class RestClientBuilder {
|
|||
//default timeouts are all infinite
|
||||
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
|
||||
.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS)
|
||||
.setSocketTimeout(DEFAULT_SOCKET_TIMEOUT_MILLIS)
|
||||
.setConnectionRequestTimeout(DEFAULT_CONNECTION_REQUEST_TIMEOUT_MILLIS);
|
||||
.setSocketTimeout(DEFAULT_SOCKET_TIMEOUT_MILLIS);
|
||||
if (requestConfigCallback != null) {
|
||||
requestConfigBuilder = requestConfigCallback.customizeRequestConfig(requestConfigBuilder);
|
||||
}
|
||||
|
|
|
@ -177,4 +177,24 @@ public class RestClientBuilderTests extends RestClientTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test verifies that we don't change the default value for the connection request timeout as that causes problems.
|
||||
* See https://github.com/elastic/elasticsearch/issues/24069
|
||||
*/
|
||||
public void testDefaultConnectionRequestTimeout() throws IOException {
|
||||
RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200));
|
||||
builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
|
||||
@Override
|
||||
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
|
||||
RequestConfig requestConfig = requestConfigBuilder.build();
|
||||
assertEquals(RequestConfig.DEFAULT.getConnectionRequestTimeout(), requestConfig.getConnectionRequestTimeout());
|
||||
//this way we get notified if the default ever changes
|
||||
assertEquals(-1, requestConfig.getConnectionRequestTimeout());
|
||||
return requestConfigBuilder;
|
||||
}
|
||||
});
|
||||
try (RestClient restClient = builder.build()) {
|
||||
assertNotNull(restClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.apache.http.entity.ContentType;
|
|||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
|
||||
import org.apache.http.nio.entity.NStringEntity;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.elasticsearch.mocksocket.MockHttpServer;
|
||||
import org.junit.AfterClass;
|
||||
|
@ -48,6 +49,9 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.elasticsearch.client.RestClientTestUtil.getAllStatusCodes;
|
||||
import static org.elasticsearch.client.RestClientTestUtil.getHttpMethods;
|
||||
|
@ -159,6 +163,42 @@ public class RestClientSingleHostIntegTests extends RestClientTestCase {
|
|||
httpServer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests sending a bunch of async requests works well (e.g. no TimeoutException from the leased pool)
|
||||
* See https://github.com/elastic/elasticsearch/issues/24069
|
||||
*/
|
||||
public void testManyAsyncRequests() throws Exception {
|
||||
int iters = randomIntBetween(500, 1000);
|
||||
final CountDownLatch latch = new CountDownLatch(iters);
|
||||
final List<Exception> exceptions = new CopyOnWriteArrayList<>();
|
||||
for (int i = 0; i < iters; i++) {
|
||||
Request request = new Request("PUT", "/200");
|
||||
request.setEntity(new NStringEntity("{}", ContentType.APPLICATION_JSON));
|
||||
restClient.performRequestAsync(request, new ResponseListener() {
|
||||
@Override
|
||||
public void onSuccess(Response response) {
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception exception) {
|
||||
exceptions.add(exception);
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
assertTrue("timeout waiting for requests to be sent", latch.await(10, TimeUnit.SECONDS));
|
||||
if (exceptions.isEmpty() == false) {
|
||||
AssertionError error = new AssertionError("expected no failures but got some. see suppressed for first 10 of ["
|
||||
+ exceptions.size() + "] failures");
|
||||
for (Exception exception : exceptions.subList(0, Math.min(10, exceptions.size()))) {
|
||||
error.addSuppressed(exception);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End to end test for headers. We test it explicitly against a real http client as there are different ways
|
||||
* to set/add headers to the {@link org.apache.http.client.HttpClient}.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
[partintro]
|
||||
--
|
||||
// To add a release, copy and paste the template text
|
||||
// To add a release, copy and paste the template text
|
||||
// and add a link to the new section. Note that release subheads must
|
||||
// be floated and sections cannot be empty.
|
||||
|
||||
|
@ -104,6 +104,8 @@ ones that the user is authorized to access in case field level security is enabl
|
|||
[float]
|
||||
=== Bug Fixes
|
||||
|
||||
Use date format in `date_range` mapping before fallback to default ({pull}29310[#29310])
|
||||
|
||||
Fix NPE in 'more_like_this' when field has zero tokens ({pull}30365[#30365])
|
||||
|
||||
Fixed prerelease version of elasticsearch in the `deb` package to sort before GA versions
|
||||
|
@ -139,8 +141,11 @@ coming[6.4.0]
|
|||
//[float]
|
||||
//=== Breaking Java Changes
|
||||
|
||||
//[float]
|
||||
//=== Deprecations
|
||||
[float]
|
||||
=== Deprecations
|
||||
|
||||
Deprecated multi-argument versions of the request methods in the RestClient.
|
||||
Prefer the "Request" object flavored methods. ({pull}30315[#30315])
|
||||
|
||||
[float]
|
||||
=== New Features
|
||||
|
@ -157,8 +162,11 @@ analysis module. ({pull}30397[#30397])
|
|||
|
||||
{ref-64}/breaking_64_api_changes.html#copy-source-settings-on-resize[Allow copying source settings on index resize operations] ({pull}30255[#30255])
|
||||
|
||||
Added new "Request" object flavored request methods. Prefer these instead of the
|
||||
multi-argument versions. ({pull}29623[#29623])
|
||||
Added new "Request" object flavored request methods in the RestClient. Prefer
|
||||
these instead of the multi-argument versions. ({pull}29623[#29623])
|
||||
|
||||
Watcher HTTP client used in watches now allows more parallel connections to the
|
||||
same endpoint and evicts long running connections. ({pull}30130[#30130])
|
||||
|
||||
The cluster state listener to decide if watcher should be
|
||||
stopped/started/paused now runs far less code in an executor but is more
|
||||
|
@ -171,6 +179,8 @@ Added put index template API to the high level rest client ({pull}30400[#30400])
|
|||
[float]
|
||||
=== Bug Fixes
|
||||
|
||||
Use date format in `date_range` mapping before fallback to default ({pull}29310[#29310])
|
||||
|
||||
Fix NPE in 'more_like_this' when field has zero tokens ({pull}30365[#30365])
|
||||
|
||||
Do not ignore request analysis/similarity settings on index resize operations when the source index already contains such settings ({pull}30216[#30216])
|
||||
|
|
|
@ -64,9 +64,10 @@ It is also possible to retrieve information for a particular task:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
GET _tasks/task_id:1 <1>
|
||||
GET _tasks/task_id <1>
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
// TEST[catch:missing]
|
||||
|
||||
<1> This will return a 404 if the task isn't found.
|
||||
|
@ -75,9 +76,10 @@ Or to retrieve all children of a particular task:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
GET _tasks?parent_task_id=parentTaskId:1 <1>
|
||||
GET _tasks?parent_task_id=parent_task_id <1>
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[s/=parent_task_id/=node_id:1/]
|
||||
|
||||
<1> This won't return a 404 if the parent isn't found.
|
||||
|
||||
|
|
|
@ -357,9 +357,10 @@ With the task id you can look up the task directly:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
GET /_tasks/taskId:1
|
||||
GET /_tasks/task_id
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
// TEST[catch:missing]
|
||||
|
||||
The advantage of this API is that it integrates with `wait_for_completion=false`
|
||||
|
@ -378,8 +379,9 @@ Any Delete By Query can be canceled using the <<tasks,Task Cancel API>>:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
POST _tasks/task_id:1/_cancel
|
||||
POST _tasks/task_id/_cancel
|
||||
--------------------------------------------------
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
// CONSOLE
|
||||
|
||||
The `task_id` can be found using the tasks API above.
|
||||
|
@ -397,8 +399,9 @@ using the `_rethrottle` API:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
POST _delete_by_query/task_id:1/_rethrottle?requests_per_second=-1
|
||||
POST _delete_by_query/task_id/_rethrottle?requests_per_second=-1
|
||||
--------------------------------------------------
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
// CONSOLE
|
||||
|
||||
The `task_id` can be found using the tasks API above.
|
||||
|
|
|
@ -740,9 +740,10 @@ With the task id you can look up the task directly:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
GET /_tasks/taskId:1
|
||||
GET /_tasks/task_id
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
// TEST[catch:missing]
|
||||
|
||||
The advantage of this API is that it integrates with `wait_for_completion=false`
|
||||
|
@ -761,9 +762,10 @@ Any Reindex can be canceled using the <<tasks,Task Cancel API>>:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
POST _tasks/task_id:1/_cancel
|
||||
POST _tasks/task_id/_cancel
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
|
||||
The `task_id` can be found using the Tasks API.
|
||||
|
||||
|
@ -780,9 +782,10 @@ the `_rethrottle` API:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
POST _reindex/task_id:1/_rethrottle?requests_per_second=-1
|
||||
POST _reindex/task_id/_rethrottle?requests_per_second=-1
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
|
||||
The `task_id` can be found using the Tasks API above.
|
||||
|
||||
|
|
|
@ -415,9 +415,10 @@ With the task id you can look up the task directly:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
GET /_tasks/taskId:1
|
||||
GET /_tasks/task_id
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
// TEST[catch:missing]
|
||||
|
||||
The advantage of this API is that it integrates with `wait_for_completion=false`
|
||||
|
@ -436,9 +437,10 @@ Any Update By Query can be canceled using the <<tasks,Task Cancel API>>:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
POST _tasks/task_id:1/_cancel
|
||||
POST _tasks/task_id/_cancel
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
|
||||
The `task_id` can be found using the tasks API above.
|
||||
|
||||
|
@ -455,9 +457,10 @@ using the `_rethrottle` API:
|
|||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
POST _update_by_query/task_id:1/_rethrottle?requests_per_second=-1
|
||||
POST _update_by_query/task_id/_rethrottle?requests_per_second=-1
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[s/task_id/node_id:1/]
|
||||
|
||||
The `task_id` can be found using the tasks API above.
|
||||
|
||||
|
|
|
@ -287,6 +287,9 @@ public class RangeFieldMapper extends FieldMapper {
|
|||
public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper,
|
||||
ShapeRelation relation, DateTimeZone timeZone, DateMathParser parser, QueryShardContext context) {
|
||||
failIfNotIndexed();
|
||||
if (parser == null) {
|
||||
parser = dateMathParser();
|
||||
}
|
||||
return rangeType.rangeQuery(name(), hasDocValues(), lowerTerm, upperTerm, includeLower, includeUpper, relation,
|
||||
timeZone, parser, context);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
|
||||
import org.apache.lucene.document.DoubleRange;
|
||||
import org.apache.lucene.document.FloatRange;
|
||||
import org.apache.lucene.document.InetAddressPoint;
|
||||
|
@ -31,13 +30,16 @@ import org.apache.lucene.queries.BinaryDocValuesRangeQuery;
|
|||
import org.apache.lucene.search.IndexOrDocValuesQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.geo.ShapeRelation;
|
||||
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
||||
import org.elasticsearch.common.joda.Joda;
|
||||
import org.elasticsearch.common.network.InetAddresses;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.IndexSettings;
|
||||
import org.elasticsearch.index.mapper.RangeFieldMapper.RangeFieldType;
|
||||
import org.elasticsearch.index.mapper.RangeFieldMapper.RangeType;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.test.IndexSettingsModule;
|
||||
|
@ -55,42 +57,38 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
|||
|
||||
@Before
|
||||
public void setupProperties() {
|
||||
type = RandomPicks.randomFrom(random(), RangeType.values());
|
||||
type = randomFrom(RangeType.values());
|
||||
nowInMillis = randomNonNegativeLong();
|
||||
if (type == RangeType.DATE) {
|
||||
addModifier(new Modifier("format", true) {
|
||||
@Override
|
||||
public void modify(MappedFieldType ft) {
|
||||
((RangeFieldMapper.RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("basic_week_date", Locale.ROOT));
|
||||
((RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("basic_week_date", Locale.ROOT));
|
||||
}
|
||||
});
|
||||
addModifier(new Modifier("locale", true) {
|
||||
@Override
|
||||
public void modify(MappedFieldType ft) {
|
||||
((RangeFieldMapper.RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("date_optional_time", Locale.CANADA));
|
||||
((RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("date_optional_time", Locale.CANADA));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RangeFieldMapper.RangeFieldType createDefaultFieldType() {
|
||||
return new RangeFieldMapper.RangeFieldType(type, Version.CURRENT);
|
||||
protected RangeFieldType createDefaultFieldType() {
|
||||
return new RangeFieldType(type, Version.CURRENT);
|
||||
}
|
||||
|
||||
public void testRangeQuery() throws Exception {
|
||||
Settings indexSettings = Settings.builder()
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
|
||||
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings);
|
||||
QueryShardContext context = new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(),
|
||||
writableRegistry(), null, null, () -> nowInMillis, null);
|
||||
RangeFieldMapper.RangeFieldType ft = new RangeFieldMapper.RangeFieldType(type, Version.CURRENT);
|
||||
QueryShardContext context = createContext();
|
||||
RangeFieldType ft = new RangeFieldType(type, Version.CURRENT);
|
||||
ft.setName(FIELDNAME);
|
||||
ft.setIndexOptions(IndexOptions.DOCS);
|
||||
|
||||
ShapeRelation relation = RandomPicks.randomFrom(random(), ShapeRelation.values());
|
||||
boolean includeLower = random().nextBoolean();
|
||||
boolean includeUpper = random().nextBoolean();
|
||||
ShapeRelation relation = randomFrom(ShapeRelation.values());
|
||||
boolean includeLower = randomBoolean();
|
||||
boolean includeUpper = randomBoolean();
|
||||
Object from = nextFrom();
|
||||
Object to = nextTo(from);
|
||||
|
||||
|
@ -98,6 +96,41 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
|||
ft.rangeQuery(from, to, includeLower, includeUpper, relation, null, null, context));
|
||||
}
|
||||
|
||||
private QueryShardContext createContext() {
|
||||
Settings indexSettings = Settings.builder()
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
|
||||
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings);
|
||||
return new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(),
|
||||
writableRegistry(), null, null, () -> nowInMillis, null);
|
||||
}
|
||||
|
||||
public void testDateRangeQueryUsingMappingFormat() {
|
||||
QueryShardContext context = createContext();
|
||||
RangeFieldType fieldType = new RangeFieldType(RangeType.DATE, Version.CURRENT);
|
||||
fieldType.setName(FIELDNAME);
|
||||
fieldType.setIndexOptions(IndexOptions.DOCS);
|
||||
fieldType.setHasDocValues(false);
|
||||
ShapeRelation relation = randomFrom(ShapeRelation.values());
|
||||
|
||||
// dates will break the default format
|
||||
final String from = "2016-15-06T15:29:50+08:00";
|
||||
final String to = "2016-16-06T15:29:50+08:00";
|
||||
|
||||
ElasticsearchParseException ex = expectThrows(ElasticsearchParseException.class,
|
||||
() -> fieldType.rangeQuery(from, to, true, true, relation, null, null, context));
|
||||
assertEquals("failed to parse date field [2016-15-06T15:29:50+08:00] with format [strict_date_optional_time||epoch_millis]",
|
||||
ex.getMessage());
|
||||
|
||||
// setting mapping format which is compatible with those dates
|
||||
final FormatDateTimeFormatter formatter = Joda.forPattern("yyyy-dd-MM'T'HH:mm:ssZZ");
|
||||
assertEquals(1465975790000L, formatter.parser().parseMillis(from));
|
||||
assertEquals(1466062190000L, formatter.parser().parseMillis(to));
|
||||
|
||||
fieldType.setDateTimeFormatter(formatter);
|
||||
final Query query = fieldType.rangeQuery(from, to, true, true, relation, null, null, context);
|
||||
assertEquals("field:<ranges:[1465975790000 : 1466062190000]>", query.toString());
|
||||
}
|
||||
|
||||
private Query getExpectedRangeQuery(ShapeRelation relation, Object from, Object to, boolean includeLower, boolean includeUpper) {
|
||||
switch (type) {
|
||||
case DATE:
|
||||
|
@ -277,14 +310,10 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
|||
assertEquals(InetAddresses.forString("::1"), RangeFieldMapper.RangeType.IP.parse(new BytesRef("::1"), randomBoolean()));
|
||||
}
|
||||
|
||||
public void testTermQuery() throws Exception, IllegalArgumentException {
|
||||
public void testTermQuery() throws Exception {
|
||||
// See https://github.com/elastic/elasticsearch/issues/25950
|
||||
Settings indexSettings = Settings.builder()
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
|
||||
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings);
|
||||
QueryShardContext context = new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(),
|
||||
writableRegistry(), null, null, () -> nowInMillis, null);
|
||||
RangeFieldMapper.RangeFieldType ft = new RangeFieldMapper.RangeFieldType(type, Version.CURRENT);
|
||||
QueryShardContext context = createContext();
|
||||
RangeFieldType ft = new RangeFieldType(type, Version.CURRENT);
|
||||
ft.setName(FIELDNAME);
|
||||
ft.setIndexOptions(IndexOptions.DOCS);
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.common.util.BigArrays;
|
|||
import org.elasticsearch.common.util.PageCacheRecycler;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.core.internal.io.IOUtils;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.env.NodeEnvironment;
|
||||
import org.elasticsearch.http.HttpServerTransport;
|
||||
|
@ -38,6 +39,7 @@ import org.elasticsearch.indices.breaker.CircuitBreakerService;
|
|||
import org.elasticsearch.ingest.Processor;
|
||||
import org.elasticsearch.license.LicenseService;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.persistent.PersistentTasksExecutor;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
import org.elasticsearch.plugins.AnalysisPlugin;
|
||||
import org.elasticsearch.plugins.ClusterPlugin;
|
||||
|
@ -57,9 +59,9 @@ import org.elasticsearch.threadpool.ThreadPool;
|
|||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.transport.TransportInterceptor;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.persistent.PersistentTasksExecutor;
|
||||
import org.elasticsearch.xpack.core.ssl.SSLService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -391,6 +393,11 @@ public class LocalStateCompositeXPackPlugin extends XPackPlugin implements Scrip
|
|||
.collect(toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
IOUtils.close(plugins);
|
||||
}
|
||||
|
||||
private <T> List<T> filterPlugins(Class<T> type) {
|
||||
return plugins.stream().filter(x -> type.isAssignableFrom(x.getClass())).map(p -> ((T)p))
|
||||
.collect(Collectors.toList());
|
||||
|
|
|
@ -197,7 +197,7 @@ import org.elasticsearch.xpack.security.rest.action.user.RestGetUsersAction;
|
|||
import org.elasticsearch.xpack.security.rest.action.user.RestHasPrivilegesAction;
|
||||
import org.elasticsearch.xpack.security.rest.action.user.RestPutUserAction;
|
||||
import org.elasticsearch.xpack.security.rest.action.user.RestSetEnabledAction;
|
||||
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor;
|
||||
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
|
||||
import org.elasticsearch.xpack.security.transport.netty4.SecurityNetty4HttpServerTransport;
|
||||
|
@ -233,7 +233,7 @@ import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETT
|
|||
import static org.elasticsearch.xpack.core.XPackSettings.HTTP_SSL_ENABLED;
|
||||
import static org.elasticsearch.xpack.core.security.SecurityLifecycleServiceField.SECURITY_TEMPLATE_NAME;
|
||||
import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME;
|
||||
import static org.elasticsearch.xpack.security.support.IndexLifecycleManager.INTERNAL_INDEX_FORMAT;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT;
|
||||
|
||||
public class Security extends Plugin implements ActionPlugin, IngestPlugin, NetworkPlugin, ClusterPlugin,
|
||||
DiscoveryPlugin, MapperPlugin, ExtensiblePlugin {
|
||||
|
@ -424,8 +424,8 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
|
|||
components.add(realms);
|
||||
components.add(reservedRealm);
|
||||
|
||||
securityLifecycleService.addSecurityIndexHealthChangeListener(nativeRoleMappingStore::onSecurityIndexHealthChange);
|
||||
securityLifecycleService.addSecurityIndexOutOfDateListener(nativeRoleMappingStore::onSecurityIndexOutOfDateChange);
|
||||
securityLifecycleService.securityIndex().addIndexHealthChangeListener(nativeRoleMappingStore::onSecurityIndexHealthChange);
|
||||
securityLifecycleService.securityIndex().addIndexOutOfDateListener(nativeRoleMappingStore::onSecurityIndexOutOfDateChange);
|
||||
|
||||
AuthenticationFailureHandler failureHandler = null;
|
||||
String extensionName = null;
|
||||
|
@ -458,8 +458,8 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
|
|||
}
|
||||
final CompositeRolesStore allRolesStore = new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore,
|
||||
reservedRolesStore, rolesProviders, threadPool.getThreadContext(), getLicenseState());
|
||||
securityLifecycleService.addSecurityIndexHealthChangeListener(allRolesStore::onSecurityIndexHealthChange);
|
||||
securityLifecycleService.addSecurityIndexOutOfDateListener(allRolesStore::onSecurityIndexOutOfDateChange);
|
||||
securityLifecycleService.securityIndex().addIndexHealthChangeListener(allRolesStore::onSecurityIndexHealthChange);
|
||||
securityLifecycleService.securityIndex().addIndexOutOfDateListener(allRolesStore::onSecurityIndexOutOfDateChange);
|
||||
// to keep things simple, just invalidate all cached entries on license change. this happens so rarely that the impact should be
|
||||
// minimal
|
||||
getLicenseState().addListener(allRolesStore::invalidateAll);
|
||||
|
@ -886,7 +886,7 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
|
|||
templates.remove(SECURITY_TEMPLATE_NAME);
|
||||
final XContent xContent = XContentFactory.xContent(XContentType.JSON);
|
||||
final byte[] auditTemplate = TemplateUtils.loadTemplate("/" + IndexAuditTrail.INDEX_TEMPLATE_NAME + ".json",
|
||||
Version.CURRENT.toString(), IndexLifecycleManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
|
||||
Version.CURRENT.toString(), SecurityIndexManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
try (XContentParser parser = xContent
|
||||
.createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, auditTemplate)) {
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.elasticsearch.common.util.concurrent.AbstractRunnable;
|
|||
import org.elasticsearch.gateway.GatewayService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
|
||||
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -46,7 +46,7 @@ import java.util.function.Predicate;
|
|||
*/
|
||||
public class SecurityLifecycleService extends AbstractComponent implements ClusterStateListener {
|
||||
|
||||
public static final String INTERNAL_SECURITY_INDEX = IndexLifecycleManager.INTERNAL_SECURITY_INDEX;
|
||||
public static final String INTERNAL_SECURITY_INDEX = SecurityIndexManager.INTERNAL_SECURITY_INDEX;
|
||||
public static final String SECURITY_INDEX_NAME = ".security";
|
||||
|
||||
private static final Version MIN_READ_VERSION = Version.V_5_0_0;
|
||||
|
@ -55,7 +55,7 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
|
|||
private final ThreadPool threadPool;
|
||||
private final IndexAuditTrail indexAuditTrail;
|
||||
|
||||
private final IndexLifecycleManager securityIndex;
|
||||
private final SecurityIndexManager securityIndex;
|
||||
|
||||
public SecurityLifecycleService(Settings settings, ClusterService clusterService,
|
||||
ThreadPool threadPool, Client client,
|
||||
|
@ -64,7 +64,7 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
|
|||
this.settings = settings;
|
||||
this.threadPool = threadPool;
|
||||
this.indexAuditTrail = indexAuditTrail;
|
||||
this.securityIndex = new IndexLifecycleManager(settings, client, SECURITY_INDEX_NAME);
|
||||
this.securityIndex = new SecurityIndexManager(settings, client, SECURITY_INDEX_NAME);
|
||||
clusterService.addListener(this);
|
||||
clusterService.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
|
@ -110,69 +110,10 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
|
|||
}
|
||||
}
|
||||
|
||||
IndexLifecycleManager securityIndex() {
|
||||
public SecurityIndexManager securityIndex() {
|
||||
return securityIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the security index exists
|
||||
*/
|
||||
public boolean isSecurityIndexExisting() {
|
||||
return securityIndex.indexExists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the security index does not exist or it exists and has the current
|
||||
* value for the <code>index.format</code> index setting
|
||||
*/
|
||||
public boolean isSecurityIndexUpToDate() {
|
||||
return securityIndex.isIndexUpToDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the security index exists and all primary shards are active
|
||||
*/
|
||||
public boolean isSecurityIndexAvailable() {
|
||||
return securityIndex.isAvailable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the security index does not exist or the mappings are up to date
|
||||
* based on the version in the <code>_meta</code> field
|
||||
*/
|
||||
public boolean isSecurityIndexMappingUpToDate() {
|
||||
return securityIndex().isMappingUpToDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the effective (active) version of the security mapping meets the
|
||||
* <code>requiredVersion</code>.
|
||||
*
|
||||
* @return <code>true</code> if the effective version passes the predicate, or the security
|
||||
* mapping does not exist (<code>null</code> version). Otherwise, <code>false</code>.
|
||||
*/
|
||||
public boolean checkSecurityMappingVersion(Predicate<Version> requiredVersion) {
|
||||
return securityIndex.checkMappingVersion(requiredVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener which will be notified when the security index health changes. The previous and
|
||||
* current health will be provided to the listener so that the listener can determine if any action
|
||||
* needs to be taken.
|
||||
*/
|
||||
public void addSecurityIndexHealthChangeListener(BiConsumer<ClusterIndexHealth, ClusterIndexHealth> listener) {
|
||||
securityIndex.addIndexHealthChangeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener which will be notified when the security index out of date value changes. The previous and
|
||||
* current value will be provided to the listener so that the listener can determine if any action
|
||||
* needs to be taken.
|
||||
*/
|
||||
void addSecurityIndexOutOfDateListener(BiConsumer<Boolean, Boolean> listener) {
|
||||
securityIndex.addIndexOutOfDateListener(listener);
|
||||
}
|
||||
|
||||
// this is called in a lifecycle listener beforeStop on the cluster service
|
||||
private void close() {
|
||||
if (indexAuditTrail != null) {
|
||||
|
@ -193,29 +134,13 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
|
|||
}
|
||||
|
||||
private static boolean checkMappingVersions(ClusterState clusterState, Logger logger, Predicate<Version> versionPredicate) {
|
||||
return IndexLifecycleManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, versionPredicate);
|
||||
return SecurityIndexManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, versionPredicate);
|
||||
}
|
||||
|
||||
public static List<String> indexNames() {
|
||||
return Collections.unmodifiableList(Arrays.asList(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the security index by creating it if it doesn't exist or updating the mappings if the mappings are
|
||||
* out of date. After any tasks have been executed, the runnable is then executed.
|
||||
*/
|
||||
public void prepareIndexIfNeededThenExecute(final Consumer<Exception> consumer, final Runnable andThen) {
|
||||
securityIndex.prepareIndexIfNeededThenExecute(consumer, andThen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the security index is out of date with the current version. If the index does not exist
|
||||
* we treat the index as up to date as we expect it to be created with the current format.
|
||||
*/
|
||||
public boolean isSecurityIndexOutOfDate() {
|
||||
return securityIndex.isIndexUpToDate() == false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the move from {@code previousHealth} to {@code currentHealth} a move from an unhealthy ("RED") index state to a healthy
|
||||
* ("non-RED") state.
|
||||
|
|
|
@ -57,7 +57,7 @@ import org.elasticsearch.xpack.core.template.TemplateUtils;
|
|||
import org.elasticsearch.xpack.security.audit.AuditLevel;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
||||
import org.elasticsearch.xpack.security.rest.RemoteHostHeader;
|
||||
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
@ -105,7 +105,7 @@ import static org.elasticsearch.xpack.security.audit.AuditLevel.parse;
|
|||
import static org.elasticsearch.xpack.security.audit.AuditUtil.indices;
|
||||
import static org.elasticsearch.xpack.security.audit.AuditUtil.restRequestContent;
|
||||
import static org.elasticsearch.xpack.security.audit.index.IndexNameResolver.resolve;
|
||||
import static org.elasticsearch.xpack.security.support.IndexLifecycleManager.SECURITY_VERSION_STRING;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_VERSION_STRING;
|
||||
|
||||
/**
|
||||
* Audit trail implementation that writes events into an index.
|
||||
|
@ -1001,7 +1001,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
|||
|
||||
private PutIndexTemplateRequest getPutIndexTemplateRequest(Settings customSettings) {
|
||||
final byte[] template = TemplateUtils.loadTemplate("/" + INDEX_TEMPLATE_NAME + ".json",
|
||||
Version.CURRENT.toString(), IndexLifecycleManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
|
||||
Version.CURRENT.toString(), SecurityIndexManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
|
||||
final PutIndexTemplateRequest request = new PutIndexTemplateRequest(INDEX_TEMPLATE_NAME).source(template, XContentType.JSON);
|
||||
if (customSettings != null && customSettings.names().size() > 0) {
|
||||
Settings updatedSettings = Settings.builder()
|
||||
|
|
|
@ -96,7 +96,7 @@ public final class InternalRealms {
|
|||
map.put(FileRealmSettings.TYPE, config -> new FileRealm(config, resourceWatcherService));
|
||||
map.put(NativeRealmSettings.TYPE, config -> {
|
||||
final NativeRealm nativeRealm = new NativeRealm(config, nativeUsersStore);
|
||||
securityLifecycleService.addSecurityIndexHealthChangeListener(nativeRealm::onSecurityIndexHealthChange);
|
||||
securityLifecycleService.securityIndex().addIndexHealthChangeListener(nativeRealm::onSecurityIndexHealthChange);
|
||||
return nativeRealm;
|
||||
});
|
||||
map.put(LdapRealmSettings.AD_TYPE, config -> new LdapRealm(LdapRealmSettings.AD_TYPE, config, sslService,
|
||||
|
|
|
@ -250,7 +250,7 @@ public final class TokenService extends AbstractComponent {
|
|||
.setSource(builder)
|
||||
.setRefreshPolicy(RefreshPolicy.WAIT_UNTIL)
|
||||
.request();
|
||||
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client, SECURITY_ORIGIN, IndexAction.INSTANCE, request,
|
||||
ActionListener.wrap(indexResponse -> listener.onResponse(new Tuple<>(userToken, refreshToken)),
|
||||
listener::onFailure))
|
||||
|
@ -354,7 +354,7 @@ public final class TokenService extends AbstractComponent {
|
|||
if (version.onOrAfter(Version.V_6_2_0)) {
|
||||
// we only have the id and need to get the token from the doc!
|
||||
decryptTokenId(in, cipher, version, ActionListener.wrap(tokenId ->
|
||||
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
final GetRequest getRequest =
|
||||
client.prepareGet(SecurityLifecycleService.SECURITY_INDEX_NAME, TYPE,
|
||||
getTokenDocumentId(tokenId)).request();
|
||||
|
@ -524,7 +524,7 @@ public final class TokenService extends AbstractComponent {
|
|||
.request();
|
||||
final String tokenDocId = getTokenDocumentId(userToken);
|
||||
final Version version = userToken.getVersion();
|
||||
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, indexRequest,
|
||||
ActionListener.<IndexResponse>wrap(indexResponse -> {
|
||||
ActionListener<Boolean> wrappedListener =
|
||||
|
@ -566,7 +566,7 @@ public final class TokenService extends AbstractComponent {
|
|||
.setVersion(documentVersion)
|
||||
.setRefreshPolicy(RefreshPolicy.WAIT_UNTIL)
|
||||
.request();
|
||||
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request,
|
||||
ActionListener.<UpdateResponse>wrap(updateResponse -> {
|
||||
if (updateResponse.getGetResult() != null
|
||||
|
@ -665,7 +665,7 @@ public final class TokenService extends AbstractComponent {
|
|||
.setVersion(true)
|
||||
.request();
|
||||
|
||||
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request,
|
||||
ActionListener.<SearchResponse>wrap(searchResponse -> {
|
||||
if (searchResponse.isTimedOut()) {
|
||||
|
@ -847,7 +847,7 @@ public final class TokenService extends AbstractComponent {
|
|||
.request();
|
||||
|
||||
final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
|
||||
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
ScrollHelper.fetchAllByEntity(client, request, new ContextPreservingActionListener<>(supplier, listener), this::parseHit));
|
||||
}
|
||||
|
||||
|
@ -914,11 +914,11 @@ public final class TokenService extends AbstractComponent {
|
|||
* have been explicitly cleared.
|
||||
*/
|
||||
private void checkIfTokenIsRevoked(UserToken userToken, ActionListener<UserToken> listener) {
|
||||
if (lifecycleService.isSecurityIndexExisting() == false) {
|
||||
if (lifecycleService.securityIndex().indexExists() == false) {
|
||||
// index doesn't exist so the token is considered valid.
|
||||
listener.onResponse(userToken);
|
||||
} else {
|
||||
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
MultiGetRequest mGetRequest = client.prepareMultiGet()
|
||||
.add(SecurityLifecycleService.SECURITY_INDEX_NAME, TYPE, getInvalidatedTokenDocumentId(userToken))
|
||||
.add(SecurityLifecycleService.SECURITY_INDEX_NAME, TYPE, getTokenDocumentId(userToken))
|
||||
|
@ -989,7 +989,7 @@ public final class TokenService extends AbstractComponent {
|
|||
}
|
||||
|
||||
private void maybeStartTokenRemover() {
|
||||
if (lifecycleService.isSecurityIndexAvailable()) {
|
||||
if (lifecycleService.securityIndex().isAvailable()) {
|
||||
if (client.threadPool().relativeTimeInMillis() - lastExpirationRunMs > deleteInterval.getMillis()) {
|
||||
expiredTokenRemover.submit(client.threadPool());
|
||||
lastExpirationRunMs = client.threadPool().relativeTimeInMillis();
|
||||
|
|
|
@ -114,7 +114,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
}
|
||||
};
|
||||
|
||||
if (securityLifecycleService.isSecurityIndexExisting() == false) {
|
||||
if (securityLifecycleService.securityIndex().indexExists() == false) {
|
||||
// TODO remove this short circuiting and fix tests that fail without this!
|
||||
listener.onResponse(Collections.emptyList());
|
||||
} else if (userNames.length == 1) { // optimization for single user lookup
|
||||
|
@ -123,7 +123,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
(uap) -> listener.onResponse(uap == null ? Collections.emptyList() : Collections.singletonList(uap.user())),
|
||||
handleException));
|
||||
} else {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
final QueryBuilder query;
|
||||
if (userNames == null || userNames.length == 0) {
|
||||
query = QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), USER_DOC_TYPE);
|
||||
|
@ -154,11 +154,11 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
* Async method to retrieve a user and their password
|
||||
*/
|
||||
private void getUserAndPassword(final String user, final ActionListener<UserAndPassword> listener) {
|
||||
if (securityLifecycleService.isSecurityIndexExisting() == false) {
|
||||
if (securityLifecycleService.securityIndex().indexExists() == false) {
|
||||
// TODO remove this short circuiting and fix tests that fail without this!
|
||||
listener.onResponse(null);
|
||||
} else {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareGet(SECURITY_INDEX_NAME,
|
||||
INDEX_TYPE, getIdForUser(USER_DOC_TYPE, user)).request(),
|
||||
|
@ -199,7 +199,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
docType = USER_DOC_TYPE;
|
||||
}
|
||||
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(docType, username))
|
||||
.setDoc(Requests.INDEX_CONTENT_TYPE, Fields.PASSWORD.getPreferredName(),
|
||||
|
@ -237,7 +237,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
* has been indexed
|
||||
*/
|
||||
private void createReservedUser(String username, char[] passwordHash, RefreshPolicy refresh, ActionListener<Void> listener) {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareIndex(SECURITY_INDEX_NAME, INDEX_TYPE,
|
||||
getIdForUser(RESERVED_USER_TYPE, username))
|
||||
|
@ -279,7 +279,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
private void updateUserWithoutPassword(final PutUserRequest putUserRequest, final ActionListener<Boolean> listener) {
|
||||
assert putUserRequest.passwordHash() == null;
|
||||
// We must have an existing document
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE,
|
||||
getIdForUser(USER_DOC_TYPE, putUserRequest.username()))
|
||||
|
@ -322,7 +322,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
|
||||
private void indexUser(final PutUserRequest putUserRequest, final ActionListener<Boolean> listener) {
|
||||
assert putUserRequest.passwordHash() != null;
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareIndex(SECURITY_INDEX_NAME, INDEX_TYPE,
|
||||
getIdForUser(USER_DOC_TYPE, putUserRequest.username()))
|
||||
|
@ -366,7 +366,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
|
||||
private void setRegularUserEnabled(final String username, final boolean enabled, final RefreshPolicy refreshPolicy,
|
||||
final ActionListener<Void> listener) {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE,
|
||||
getIdForUser(USER_DOC_TYPE, username))
|
||||
|
@ -401,7 +401,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
|
||||
private void setReservedUserEnabled(final String username, final boolean enabled, final RefreshPolicy refreshPolicy,
|
||||
boolean clearCache, final ActionListener<Void> listener) {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE,
|
||||
getIdForUser(RESERVED_USER_TYPE, username))
|
||||
|
@ -431,7 +431,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
}
|
||||
|
||||
public void deleteUser(final DeleteUserRequest deleteUserRequest, final ActionListener<Boolean> listener) {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
DeleteRequest request = client.prepareDelete(SECURITY_INDEX_NAME,
|
||||
INDEX_TYPE, getIdForUser(USER_DOC_TYPE, deleteUserRequest.username())).request();
|
||||
request.setRefreshPolicy(deleteUserRequest.getRefreshPolicy());
|
||||
|
@ -470,11 +470,11 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
}
|
||||
|
||||
void getReservedUserInfo(String username, ActionListener<ReservedUserInfo> listener) {
|
||||
if (securityLifecycleService.isSecurityIndexExisting() == false) {
|
||||
if (securityLifecycleService.securityIndex().indexExists() == false) {
|
||||
// TODO remove this short circuiting and fix tests that fail without this!
|
||||
listener.onResponse(null);
|
||||
} else {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareGet(SECURITY_INDEX_NAME, INDEX_TYPE,
|
||||
getIdForUser(RESERVED_USER_TYPE, username)).request(),
|
||||
|
@ -514,7 +514,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
}
|
||||
|
||||
void getAllReservedUserInfo(ActionListener<Map<String, ReservedUserInfo>> listener) {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareSearch(SECURITY_INDEX_NAME)
|
||||
.setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), RESERVED_USER_TYPE))
|
||||
|
|
|
@ -191,7 +191,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
if (userIsDefinedForCurrentSecurityMapping(username) == false) {
|
||||
logger.debug("Marking user [{}] as disabled because the security mapping is not at the required version", username);
|
||||
listener.onResponse(DISABLED_DEFAULT_USER_INFO.deepClone());
|
||||
} else if (securityLifecycleService.isSecurityIndexExisting() == false) {
|
||||
} else if (securityLifecycleService.securityIndex().indexExists() == false) {
|
||||
listener.onResponse(getDefaultUserInfo(username));
|
||||
} else {
|
||||
nativeUsersStore.getReservedUserInfo(username, ActionListener.wrap((userInfo) -> {
|
||||
|
@ -218,7 +218,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
|
||||
private boolean userIsDefinedForCurrentSecurityMapping(String username) {
|
||||
final Version requiredVersion = getDefinedVersion(username);
|
||||
return securityLifecycleService.checkSecurityMappingVersion(requiredVersion::onOrBefore);
|
||||
return securityLifecycleService.securityIndex().checkMappingVersion(requiredVersion::onOrBefore);
|
||||
}
|
||||
|
||||
private Version getDefinedVersion(String username) {
|
||||
|
|
|
@ -120,7 +120,7 @@ public class NativeRoleMappingStore extends AbstractComponent implements UserRol
|
|||
* <em>package private</em> for unit testing
|
||||
*/
|
||||
void loadMappings(ActionListener<List<ExpressionRoleMapping>> listener) {
|
||||
if (securityLifecycleService.isSecurityIndexOutOfDate()) {
|
||||
if (securityLifecycleService.securityIndex().isIndexUpToDate() == false) {
|
||||
listener.onFailure(new IllegalStateException(
|
||||
"Security index is not on the current version - the native realm will not be operational until " +
|
||||
"the upgrade API is run on the security index"));
|
||||
|
@ -176,7 +176,7 @@ public class NativeRoleMappingStore extends AbstractComponent implements UserRol
|
|||
|
||||
private <Request, Result> void modifyMapping(String name, CheckedBiConsumer<Request, ActionListener<Result>, Exception> inner,
|
||||
Request request, ActionListener<Result> listener) {
|
||||
if (securityLifecycleService.isSecurityIndexOutOfDate()) {
|
||||
if (securityLifecycleService.securityIndex().isIndexUpToDate() == false) {
|
||||
listener.onFailure(new IllegalStateException(
|
||||
"Security index is not on the current version - the native realm will not be operational until " +
|
||||
"the upgrade API is run on the security index"));
|
||||
|
@ -192,7 +192,7 @@ public class NativeRoleMappingStore extends AbstractComponent implements UserRol
|
|||
|
||||
private void innerPutMapping(PutRoleMappingRequest request, ActionListener<Boolean> listener) {
|
||||
final ExpressionRoleMapping mapping = request.getMapping();
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
final XContentBuilder xContentBuilder;
|
||||
try {
|
||||
xContentBuilder = mapping.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS, true);
|
||||
|
@ -222,7 +222,7 @@ public class NativeRoleMappingStore extends AbstractComponent implements UserRol
|
|||
}
|
||||
|
||||
private void innerDeleteMapping(DeleteRoleMappingRequest request, ActionListener<Boolean> listener) throws IOException {
|
||||
if (securityLifecycleService.isSecurityIndexOutOfDate()) {
|
||||
if (securityLifecycleService.securityIndex().isIndexUpToDate() == false) {
|
||||
listener.onFailure(new IllegalStateException(
|
||||
"Security index is not on the current version - the native realm will not be operational until " +
|
||||
"the upgrade API is run on the security index"));
|
||||
|
@ -276,16 +276,16 @@ public class NativeRoleMappingStore extends AbstractComponent implements UserRol
|
|||
}
|
||||
|
||||
private void getMappings(ActionListener<List<ExpressionRoleMapping>> listener) {
|
||||
if (securityLifecycleService.isSecurityIndexAvailable()) {
|
||||
if (securityLifecycleService.securityIndex().isAvailable()) {
|
||||
loadMappings(listener);
|
||||
} else {
|
||||
logger.info("The security index is not yet available - no role mappings can be loaded");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Security Index [{}] [exists: {}] [available: {}] [mapping up to date: {}]",
|
||||
SECURITY_INDEX_NAME,
|
||||
securityLifecycleService.isSecurityIndexExisting(),
|
||||
securityLifecycleService.isSecurityIndexAvailable(),
|
||||
securityLifecycleService.isSecurityIndexMappingUpToDate()
|
||||
securityLifecycleService.securityIndex().indexExists(),
|
||||
securityLifecycleService.securityIndex().isAvailable(),
|
||||
securityLifecycleService.securityIndex().isMappingUpToDate()
|
||||
);
|
||||
}
|
||||
listener.onResponse(Collections.emptyList());
|
||||
|
@ -302,7 +302,7 @@ public class NativeRoleMappingStore extends AbstractComponent implements UserRol
|
|||
* </ul>
|
||||
*/
|
||||
public void usageStats(ActionListener<Map<String, Object>> listener) {
|
||||
if (securityLifecycleService.isSecurityIndexExisting() == false) {
|
||||
if (securityLifecycleService.securityIndex().indexExists() == false) {
|
||||
reportStats(listener, Collections.emptyList());
|
||||
} else {
|
||||
getMappings(ActionListener.wrap(mappings -> reportStats(listener, mappings), listener::onFailure));
|
||||
|
|
|
@ -100,7 +100,7 @@ public class NativeRolesStore extends AbstractComponent {
|
|||
* Retrieve a list of roles, if rolesToGet is null or empty, fetch all roles
|
||||
*/
|
||||
public void getRoleDescriptors(String[] names, final ActionListener<Collection<RoleDescriptor>> listener) {
|
||||
if (securityLifecycleService.isSecurityIndexExisting() == false) {
|
||||
if (securityLifecycleService.securityIndex().indexExists() == false) {
|
||||
// TODO remove this short circuiting and fix tests that fail without this!
|
||||
listener.onResponse(Collections.emptyList());
|
||||
} else if (names != null && names.length == 1) {
|
||||
|
@ -108,7 +108,7 @@ public class NativeRolesStore extends AbstractComponent {
|
|||
listener.onResponse(roleDescriptor == null ? Collections.emptyList() : Collections.singletonList(roleDescriptor)),
|
||||
listener::onFailure));
|
||||
} else {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
QueryBuilder query;
|
||||
if (names == null || names.length == 0) {
|
||||
query = QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE);
|
||||
|
@ -133,7 +133,7 @@ public class NativeRolesStore extends AbstractComponent {
|
|||
}
|
||||
|
||||
public void deleteRole(final DeleteRoleRequest deleteRoleRequest, final ActionListener<Boolean> listener) {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
DeleteRequest request = client.prepareDelete(SecurityLifecycleService.SECURITY_INDEX_NAME,
|
||||
ROLE_DOC_TYPE, getIdForUser(deleteRoleRequest.name())).request();
|
||||
request.setRefreshPolicy(deleteRoleRequest.getRefreshPolicy());
|
||||
|
@ -166,7 +166,7 @@ public class NativeRolesStore extends AbstractComponent {
|
|||
|
||||
// pkg-private for testing
|
||||
void innerPutRole(final PutRoleRequest request, final RoleDescriptor role, final ActionListener<Boolean> listener) {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
final XContentBuilder xContentBuilder;
|
||||
try {
|
||||
xContentBuilder = role.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS, true);
|
||||
|
@ -197,13 +197,13 @@ public class NativeRolesStore extends AbstractComponent {
|
|||
|
||||
public void usageStats(ActionListener<Map<String, Object>> listener) {
|
||||
Map<String, Object> usageStats = new HashMap<>();
|
||||
if (securityLifecycleService.isSecurityIndexExisting() == false) {
|
||||
if (securityLifecycleService.securityIndex().indexExists() == false) {
|
||||
usageStats.put("size", 0L);
|
||||
usageStats.put("fls", false);
|
||||
usageStats.put("dls", false);
|
||||
listener.onResponse(usageStats);
|
||||
} else {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareMultiSearch()
|
||||
.add(client.prepareSearch(SecurityLifecycleService.SECURITY_INDEX_NAME)
|
||||
|
@ -259,11 +259,11 @@ public class NativeRolesStore extends AbstractComponent {
|
|||
}
|
||||
|
||||
private void getRoleDescriptor(final String roleId, ActionListener<RoleDescriptor> roleActionListener) {
|
||||
if (securityLifecycleService.isSecurityIndexExisting() == false) {
|
||||
if (securityLifecycleService.securityIndex().indexExists() == false) {
|
||||
// TODO remove this short circuiting and fix tests that fail without this!
|
||||
roleActionListener.onResponse(null);
|
||||
} else {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(roleActionListener::onFailure, () ->
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(roleActionListener::onFailure, () ->
|
||||
executeGetRoleRequest(roleId, new ActionListener<GetResponse>() {
|
||||
@Override
|
||||
public void onResponse(GetResponse response) {
|
||||
|
@ -288,7 +288,7 @@ public class NativeRolesStore extends AbstractComponent {
|
|||
}
|
||||
|
||||
private void executeGetRoleRequest(String role, ActionListener<GetResponse> listener) {
|
||||
securityLifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
securityLifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareGet(SecurityLifecycleService.SECURITY_INDEX_NAME,
|
||||
ROLE_DOC_TYPE, getIdForUser(role)).request(),
|
||||
|
|
|
@ -58,7 +58,7 @@ import static org.elasticsearch.xpack.core.security.SecurityLifecycleServiceFiel
|
|||
/**
|
||||
* Manages the lifecycle of a single index, its template, mapping and and data upgrades/migrations.
|
||||
*/
|
||||
public class IndexLifecycleManager extends AbstractComponent {
|
||||
public class SecurityIndexManager extends AbstractComponent {
|
||||
|
||||
public static final String INTERNAL_SECURITY_INDEX = ".security-" + IndexUpgradeCheckVersion.UPRADE_VERSION;
|
||||
public static final int INTERNAL_INDEX_FORMAT = 6;
|
||||
|
@ -74,7 +74,7 @@ public class IndexLifecycleManager extends AbstractComponent {
|
|||
|
||||
private volatile State indexState = new State(false, false, false, false, null);
|
||||
|
||||
public IndexLifecycleManager(Settings settings, Client client, String indexName) {
|
||||
public SecurityIndexManager(Settings settings, Client client, String indexName) {
|
||||
super(settings);
|
||||
this.client = client;
|
||||
this.indexName = indexName;
|
||||
|
@ -347,7 +347,7 @@ public class IndexLifecycleManager extends AbstractComponent {
|
|||
|
||||
private Tuple<String, Settings> loadMappingAndSettingsSourceFromTemplate() {
|
||||
final byte[] template = TemplateUtils.loadTemplate("/" + SECURITY_TEMPLATE_NAME + ".json",
|
||||
Version.CURRENT.toString(), IndexLifecycleManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
|
||||
Version.CURRENT.toString(), SecurityIndexManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
|
||||
PutIndexTemplateRequest request = new PutIndexTemplateRequest(SECURITY_TEMPLATE_NAME).source(template, XContentType.JSON);
|
||||
return new Tuple<>(request.mappings().get("doc"), request.settings());
|
||||
}
|
|
@ -37,7 +37,7 @@ import org.elasticsearch.threadpool.ThreadPool;
|
|||
import org.elasticsearch.transport.MockTransportClient;
|
||||
import org.elasticsearch.xpack.core.security.SecurityLifecycleServiceField;
|
||||
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
|
||||
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.elasticsearch.xpack.security.test.SecurityTestUtils;
|
||||
import org.elasticsearch.xpack.core.template.TemplateUtils;
|
||||
import org.junit.After;
|
||||
|
@ -105,10 +105,10 @@ public class SecurityLifecycleServiceTests extends ESTestCase {
|
|||
ClusterState.Builder clusterStateBuilder = createClusterStateWithTemplate(templateString);
|
||||
final ClusterState clusterState = clusterStateBuilder.build();
|
||||
|
||||
assertTrue(IndexLifecycleManager.checkTemplateExistsAndVersionMatches(
|
||||
assertTrue(SecurityIndexManager.checkTemplateExistsAndVersionMatches(
|
||||
SecurityLifecycleServiceField.SECURITY_TEMPLATE_NAME, clusterState, logger,
|
||||
Version.V_5_0_0::before));
|
||||
assertFalse(IndexLifecycleManager.checkTemplateExistsAndVersionMatches(
|
||||
assertFalse(SecurityIndexManager.checkTemplateExistsAndVersionMatches(
|
||||
SecurityLifecycleServiceField.SECURITY_TEMPLATE_NAME, clusterState, logger,
|
||||
Version.V_5_0_0::after));
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase {
|
|||
ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString);
|
||||
securityLifecycleService.clusterChanged(new ClusterChangedEvent("test-event",
|
||||
clusterStateBuilder.build(), EMPTY_CLUSTER_STATE));
|
||||
final IndexLifecycleManager securityIndex = securityLifecycleService.securityIndex();
|
||||
final SecurityIndexManager securityIndex = securityLifecycleService.securityIndex();
|
||||
assertTrue(securityIndex.checkMappingVersion(Version.V_5_0_0::before));
|
||||
assertFalse(securityIndex.checkMappingVersion(Version.V_5_0_0::after));
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase {
|
|||
|
||||
private static IndexMetaData.Builder createIndexMetadata(String indexName, String templateString) throws IOException {
|
||||
String template = TemplateUtils.loadTemplate(templateString, Version.CURRENT.toString(),
|
||||
IndexLifecycleManager.TEMPLATE_VERSION_PATTERN);
|
||||
SecurityIndexManager.TEMPLATE_VERSION_PATTERN);
|
||||
PutIndexTemplateRequest request = new PutIndexTemplateRequest();
|
||||
request.source(template, XContentType.JSON);
|
||||
IndexMetaData.Builder indexMetaData = IndexMetaData.builder(indexName);
|
||||
|
@ -219,7 +219,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase {
|
|||
String templateName, String templateString) throws IOException {
|
||||
|
||||
String template = TemplateUtils.loadTemplate(templateString, Version.CURRENT.toString(),
|
||||
IndexLifecycleManager.TEMPLATE_VERSION_PATTERN);
|
||||
SecurityIndexManager.TEMPLATE_VERSION_PATTERN);
|
||||
PutIndexTemplateRequest request = new PutIndexTemplateRequest();
|
||||
request.source(template, XContentType.JSON);
|
||||
IndexTemplateMetaData.Builder templateBuilder = IndexTemplateMetaData.builder(templateName)
|
||||
|
|
|
@ -63,7 +63,7 @@ import java.util.function.Predicate;
|
|||
|
||||
import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING;
|
||||
import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME;
|
||||
import static org.elasticsearch.xpack.security.support.IndexLifecycleManager.INTERNAL_INDEX_FORMAT;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
|
|
|
@ -67,6 +67,7 @@ import org.elasticsearch.xpack.security.authc.saml.SamlRealm;
|
|||
import org.elasticsearch.xpack.security.authc.saml.SamlRealmTestHelper;
|
||||
import org.elasticsearch.xpack.security.authc.saml.SamlRealmTests;
|
||||
import org.elasticsearch.xpack.security.authc.saml.SamlTestCase;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.opensaml.saml.saml2.core.NameID;
|
||||
|
@ -161,10 +162,12 @@ public class TransportSamlInvalidateSessionActionTests extends SamlTestCase {
|
|||
};
|
||||
|
||||
final SecurityLifecycleService lifecycleService = mock(SecurityLifecycleService.class);
|
||||
final SecurityIndexManager securityIndex = mock(SecurityIndexManager.class);
|
||||
when(lifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
doAnswer(inv -> {
|
||||
((Runnable) inv.getArguments()[1]).run();
|
||||
return null;
|
||||
}).when(lifecycleService).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
}).when(securityIndex).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
|
||||
final ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
|
||||
tokenService = new TokenService(settings, Clock.systemUTC(), client, lifecycleService, clusterService);
|
||||
|
|
|
@ -56,6 +56,7 @@ import org.elasticsearch.xpack.security.authc.saml.SamlRealm;
|
|||
import org.elasticsearch.xpack.security.authc.saml.SamlRealmTests;
|
||||
import org.elasticsearch.xpack.security.authc.saml.SamlTestCase;
|
||||
import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.opensaml.saml.saml2.core.NameID;
|
||||
|
@ -173,10 +174,12 @@ public class TransportSamlLogoutActionTests extends SamlTestCase {
|
|||
}).when(client).execute(eq(IndexAction.INSTANCE), any(IndexRequest.class), any(ActionListener.class));
|
||||
|
||||
final SecurityLifecycleService lifecycleService = mock(SecurityLifecycleService.class);
|
||||
final SecurityIndexManager securityIndex = mock(SecurityIndexManager.class);
|
||||
when(lifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
doAnswer(inv -> {
|
||||
((Runnable) inv.getArguments()[1]).run();
|
||||
return null;
|
||||
}).when(lifecycleService).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
}).when(securityIndex).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
|
||||
final ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
|
||||
tokenService = new TokenService(settings, Clock.systemUTC(), client, lifecycleService, clusterService);
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
|||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealmTests;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.Before;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
@ -76,7 +77,9 @@ public class TransportGetUsersActionTests extends ESTestCase {
|
|||
public void testAnonymousUser() {
|
||||
NativeUsersStore usersStore = mock(NativeUsersStore.class);
|
||||
SecurityLifecycleService securityLifecycleService = mock(SecurityLifecycleService.class);
|
||||
when(securityLifecycleService.isSecurityIndexAvailable()).thenReturn(true);
|
||||
SecurityIndexManager securityIndex = mock(SecurityIndexManager.class);
|
||||
when(securityLifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
AnonymousUser anonymousUser = new AnonymousUser(settings);
|
||||
ReservedRealm reservedRealm =
|
||||
new ReservedRealm(mock(Environment.class), settings, usersStore, anonymousUser, securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
|
@ -146,8 +149,10 @@ public class TransportGetUsersActionTests extends ESTestCase {
|
|||
public void testReservedUsersOnly() {
|
||||
NativeUsersStore usersStore = mock(NativeUsersStore.class);
|
||||
SecurityLifecycleService securityLifecycleService = mock(SecurityLifecycleService.class);
|
||||
when(securityLifecycleService.isSecurityIndexAvailable()).thenReturn(true);
|
||||
when(securityLifecycleService.checkSecurityMappingVersion(any())).thenReturn(true);
|
||||
SecurityIndexManager securityIndex = mock(SecurityIndexManager.class);
|
||||
when(securityLifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
when(securityIndex.checkMappingVersion(any())).thenReturn(true);
|
||||
|
||||
ReservedRealmTests.mockGetAllReservedUserInfo(usersStore, Collections.emptyMap());
|
||||
ReservedRealm reservedRealm =
|
||||
|
@ -194,7 +199,9 @@ public class TransportGetUsersActionTests extends ESTestCase {
|
|||
Arrays.asList(new User("jane"), new User("fred")), randomUsers());
|
||||
NativeUsersStore usersStore = mock(NativeUsersStore.class);
|
||||
SecurityLifecycleService securityLifecycleService = mock(SecurityLifecycleService.class);
|
||||
when(securityLifecycleService.isSecurityIndexAvailable()).thenReturn(true);
|
||||
SecurityIndexManager securityIndex = mock(SecurityIndexManager.class);
|
||||
when(securityLifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
ReservedRealmTests.mockGetAllReservedUserInfo(usersStore, Collections.emptyMap());
|
||||
ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore, new AnonymousUser(settings),
|
||||
securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
|||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealmTests;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
|
@ -118,7 +119,9 @@ public class TransportPutUserActionTests extends ESTestCase {
|
|||
public void testReservedUser() {
|
||||
NativeUsersStore usersStore = mock(NativeUsersStore.class);
|
||||
SecurityLifecycleService securityLifecycleService = mock(SecurityLifecycleService.class);
|
||||
when(securityLifecycleService.isSecurityIndexAvailable()).thenReturn(true);
|
||||
SecurityIndexManager securityIndex = mock(SecurityIndexManager.class);
|
||||
when(securityLifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
ReservedRealmTests.mockGetAllReservedUserInfo(usersStore, Collections.emptyMap());
|
||||
Settings settings = Settings.builder().put("path.home", createTempDir()).build();
|
||||
ReservedRealm reservedRealm = new ReservedRealm(TestEnvironment.newEnvironment(settings), settings, usersStore,
|
||||
|
|
|
@ -68,6 +68,7 @@ import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
|||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationService.Authenticator;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
|
@ -125,6 +126,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
private ThreadContext threadContext;
|
||||
private TokenService tokenService;
|
||||
private SecurityLifecycleService lifecycleService;
|
||||
private SecurityIndexManager securityIndex;
|
||||
private Client client;
|
||||
private InetSocketAddress remoteAddress;
|
||||
|
||||
|
@ -181,11 +183,13 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
return builder;
|
||||
}).when(client).prepareGet(anyString(), anyString(), anyString());
|
||||
lifecycleService = mock(SecurityLifecycleService.class);
|
||||
securityIndex = mock(SecurityIndexManager.class);
|
||||
when(lifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
doAnswer(invocationOnMock -> {
|
||||
Runnable runnable = (Runnable) invocationOnMock.getArguments()[1];
|
||||
runnable.run();
|
||||
return null;
|
||||
}).when(lifecycleService).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
}).when(securityIndex).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
|
||||
tokenService = new TokenService(settings, Clock.systemUTC(), client, lifecycleService, clusterService);
|
||||
service = new AuthenticationService(settings, realms, auditTrail,
|
||||
|
@ -924,8 +928,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testExpiredToken() throws Exception {
|
||||
when(lifecycleService.isSecurityIndexAvailable()).thenReturn(true);
|
||||
when(lifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
when(lifecycleService.securityIndex().indexExists()).thenReturn(true);
|
||||
User user = new User("_username", "r1");
|
||||
final Authentication expected = new Authentication(user, new RealmRef("realm", "custom", "node"), null);
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
|
@ -963,7 +967,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
doAnswer(invocationOnMock -> {
|
||||
((Runnable) invocationOnMock.getArguments()[1]).run();
|
||||
return null;
|
||||
}).when(lifecycleService).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
}).when(securityIndex).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
|
||||
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
|
||||
threadContext.putHeader("Authorization", "Bearer " + token);
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.elasticsearch.xpack.core.ssl.SSLService;
|
|||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
||||
import org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
@ -30,11 +31,14 @@ import static org.mockito.Matchers.isA;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class InternalRealmsTests extends ESTestCase {
|
||||
|
||||
public void testNativeRealmRegistersIndexHealthChangeListener() throws Exception {
|
||||
SecurityLifecycleService lifecycleService = mock(SecurityLifecycleService.class);
|
||||
SecurityIndexManager securityIndex = mock(SecurityIndexManager.class);
|
||||
when(lifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
Map<String, Realm.Factory> factories = InternalRealms.getFactories(mock(ThreadPool.class), mock(ResourceWatcherService.class),
|
||||
mock(SSLService.class), mock(NativeUsersStore.class), mock(NativeRoleMappingStore.class), lifecycleService);
|
||||
assertThat(factories, hasEntry(is(NativeRealmSettings.TYPE), any(Realm.Factory.class)));
|
||||
|
@ -43,10 +47,10 @@ public class InternalRealmsTests extends ESTestCase {
|
|||
Settings settings = Settings.builder().put("path.home", createTempDir()).build();
|
||||
factories.get(NativeRealmSettings.TYPE).create(new RealmConfig("test", Settings.EMPTY, settings,
|
||||
TestEnvironment.newEnvironment(settings), new ThreadContext(settings)));
|
||||
verify(lifecycleService).addSecurityIndexHealthChangeListener(isA(BiConsumer.class));
|
||||
verify(securityIndex).addIndexHealthChangeListener(isA(BiConsumer.class));
|
||||
|
||||
factories.get(NativeRealmSettings.TYPE).create(new RealmConfig("test", Settings.EMPTY, settings,
|
||||
TestEnvironment.newEnvironment(settings), new ThreadContext(settings)));
|
||||
verify(lifecycleService, times(2)).addSecurityIndexHealthChangeListener(isA(BiConsumer.class));
|
||||
verify(securityIndex, times(2)).addIndexHealthChangeListener(isA(BiConsumer.class));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.elasticsearch.xpack.core.security.authc.TokenMetaData;
|
|||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.ClockMock;
|
||||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -86,6 +87,7 @@ public class TokenServiceTests extends ESTestCase {
|
|||
|
||||
private Client client;
|
||||
private SecurityLifecycleService lifecycleService;
|
||||
private SecurityIndexManager securityIndex;
|
||||
private ClusterService clusterService;
|
||||
private Settings tokenServiceEnabledSettings = Settings.builder()
|
||||
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
|
||||
|
@ -131,11 +133,13 @@ public class TokenServiceTests extends ESTestCase {
|
|||
|
||||
// setup lifecycle service
|
||||
lifecycleService = mock(SecurityLifecycleService.class);
|
||||
securityIndex = mock(SecurityIndexManager.class);
|
||||
when(lifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
doAnswer(invocationOnMock -> {
|
||||
Runnable runnable = (Runnable) invocationOnMock.getArguments()[1];
|
||||
runnable.run();
|
||||
return null;
|
||||
}).when(lifecycleService).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
}).when(securityIndex).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
this.clusterService = ClusterServiceUtils.createClusterService(threadPool);
|
||||
}
|
||||
|
||||
|
@ -376,7 +380,7 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testInvalidatedToken() throws Exception {
|
||||
when(lifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
TokenService tokenService =
|
||||
new TokenService(tokenServiceEnabledSettings, systemUTC(), client, lifecycleService, clusterService);
|
||||
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
|
||||
|
@ -563,8 +567,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
UserToken serialized = future.get();
|
||||
assertEquals(authentication, serialized.getAuthentication());
|
||||
|
||||
when(lifecycleService.isSecurityIndexAvailable()).thenReturn(false);
|
||||
when(lifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.isAvailable()).thenReturn(false);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
future = new PlainActionFuture<>();
|
||||
tokenService.getAndValidateToken(requestContext, future);
|
||||
assertNull(future.get());
|
||||
|
|
|
@ -55,7 +55,7 @@ import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDI
|
|||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout;
|
||||
import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME;
|
||||
import static org.elasticsearch.xpack.security.support.IndexLifecycleManager.INTERNAL_SECURITY_INDEX;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_SECURITY_INDEX;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.elasticsearch.xpack.core.security.user.KibanaUser;
|
|||
import org.elasticsearch.xpack.core.security.user.LogstashSystemUser;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -236,16 +237,17 @@ public class NativeUsersStoreTests extends ESTestCase {
|
|||
|
||||
private NativeUsersStore startNativeUsersStore() {
|
||||
SecurityLifecycleService securityLifecycleService = mock(SecurityLifecycleService.class);
|
||||
when(securityLifecycleService.isSecurityIndexAvailable()).thenReturn(true);
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityLifecycleService.isSecurityIndexMappingUpToDate()).thenReturn(true);
|
||||
when(securityLifecycleService.isSecurityIndexOutOfDate()).thenReturn(false);
|
||||
when(securityLifecycleService.isSecurityIndexUpToDate()).thenReturn(true);
|
||||
SecurityIndexManager securityIndex = mock(SecurityIndexManager.class);
|
||||
when(securityLifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
when(securityIndex.isMappingUpToDate()).thenReturn(true);
|
||||
when(securityIndex.isIndexUpToDate()).thenReturn(true);
|
||||
doAnswer((i) -> {
|
||||
Runnable action = (Runnable) i.getArguments()[1];
|
||||
action.run();
|
||||
return null;
|
||||
}).when(securityLifecycleService).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
}).when(securityIndex).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
return new NativeUsersStore(Settings.EMPTY, client, securityLifecycleService);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.elasticsearch.xpack.core.security.user.User;
|
|||
import org.elasticsearch.xpack.core.security.user.UsernamesField;
|
||||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore.ReservedUserInfo;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.Before;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
|
@ -63,13 +64,16 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
private static final SecureString EMPTY_PASSWORD = new SecureString("".toCharArray());
|
||||
private NativeUsersStore usersStore;
|
||||
private SecurityLifecycleService securityLifecycleService;
|
||||
private SecurityIndexManager securityIndex;
|
||||
|
||||
@Before
|
||||
public void setupMocks() throws Exception {
|
||||
usersStore = mock(NativeUsersStore.class);
|
||||
securityLifecycleService = mock(SecurityLifecycleService.class);
|
||||
when(securityLifecycleService.isSecurityIndexAvailable()).thenReturn(true);
|
||||
when(securityLifecycleService.checkSecurityMappingVersion(any())).thenReturn(true);
|
||||
securityIndex = mock(SecurityIndexManager.class);
|
||||
when(securityLifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
when(securityIndex.checkMappingVersion(any())).thenReturn(true);
|
||||
mockGetAllReservedUserInfo(usersStore, Collections.emptyMap());
|
||||
}
|
||||
|
||||
|
@ -90,7 +94,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
Settings settings = Settings.builder().put(XPackSettings.RESERVED_REALM_ENABLED_SETTING.getKey(), false).build();
|
||||
final boolean securityIndexExists = randomBoolean();
|
||||
if (securityIndexExists) {
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
}
|
||||
final ReservedRealm reservedRealm =
|
||||
new ReservedRealm(mock(Environment.class), settings, usersStore,
|
||||
|
@ -120,7 +124,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
final User expectedUser = randomReservedUser(enabled);
|
||||
final String principal = expectedUser.principal();
|
||||
final SecureString newPassword = new SecureString("foobar".toCharArray());
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
doAnswer((i) -> {
|
||||
ActionListener callback = (ActionListener) i.getArguments()[1];
|
||||
callback.onResponse(new ReservedUserInfo(Hasher.BCRYPT.hash(newPassword), enabled, false));
|
||||
|
@ -146,10 +150,10 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
assertEquals(expectedUser, authenticated);
|
||||
assertThat(expectedUser.enabled(), is(enabled));
|
||||
|
||||
verify(securityLifecycleService, times(2)).isSecurityIndexExisting();
|
||||
verify(securityIndex, times(2)).indexExists();
|
||||
verify(usersStore, times(2)).getReservedUserInfo(eq(principal), any(ActionListener.class));
|
||||
final ArgumentCaptor<Predicate> predicateCaptor = ArgumentCaptor.forClass(Predicate.class);
|
||||
verify(securityLifecycleService, times(2)).checkSecurityMappingVersion(predicateCaptor.capture());
|
||||
verify(securityIndex, times(2)).checkMappingVersion(predicateCaptor.capture());
|
||||
verifyVersionPredicate(principal, predicateCaptor.getValue());
|
||||
verifyNoMoreInteractions(usersStore);
|
||||
}
|
||||
|
@ -165,10 +169,10 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
reservedRealm.doLookupUser(principal, listener);
|
||||
final User user = listener.actionGet();
|
||||
assertEquals(expectedUser, user);
|
||||
verify(securityLifecycleService).isSecurityIndexExisting();
|
||||
verify(securityIndex).indexExists();
|
||||
|
||||
final ArgumentCaptor<Predicate> predicateCaptor = ArgumentCaptor.forClass(Predicate.class);
|
||||
verify(securityLifecycleService).checkSecurityMappingVersion(predicateCaptor.capture());
|
||||
verify(securityIndex).checkMappingVersion(predicateCaptor.capture());
|
||||
verifyVersionPredicate(principal, predicateCaptor.getValue());
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
|
@ -199,7 +203,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
final User expectedUser = randomReservedUser(true);
|
||||
final String principal = expectedUser.principal();
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
final RuntimeException e = new RuntimeException("store threw");
|
||||
doAnswer((i) -> {
|
||||
ActionListener callback = (ActionListener) i.getArguments()[1];
|
||||
|
@ -212,11 +216,11 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class, future::actionGet);
|
||||
assertThat(securityException.getMessage(), containsString("failed to lookup"));
|
||||
|
||||
verify(securityLifecycleService).isSecurityIndexExisting();
|
||||
verify(securityIndex).indexExists();
|
||||
verify(usersStore).getReservedUserInfo(eq(principal), any(ActionListener.class));
|
||||
|
||||
final ArgumentCaptor<Predicate> predicateCaptor = ArgumentCaptor.forClass(Predicate.class);
|
||||
verify(securityLifecycleService).checkSecurityMappingVersion(predicateCaptor.capture());
|
||||
verify(securityIndex).checkMappingVersion(predicateCaptor.capture());
|
||||
verifyVersionPredicate(principal, predicateCaptor.getValue());
|
||||
|
||||
verifyNoMoreInteractions(usersStore);
|
||||
|
@ -269,7 +273,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testFailedAuthentication() throws Exception {
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
SecureString password = new SecureString("password".toCharArray());
|
||||
char[] hash = Hasher.BCRYPT.hash(password);
|
||||
ReservedUserInfo userInfo = new ReservedUserInfo(hash, true, false);
|
||||
|
@ -302,7 +306,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
MockSecureSettings mockSecureSettings = new MockSecureSettings();
|
||||
mockSecureSettings.setString("bootstrap.password", "foobar");
|
||||
Settings settings = Settings.builder().setSecureSettings(mockSecureSettings).build();
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
|
||||
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore,
|
||||
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
|
@ -324,7 +328,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
MockSecureSettings mockSecureSettings = new MockSecureSettings();
|
||||
mockSecureSettings.setString("bootstrap.password", "foobar");
|
||||
Settings settings = Settings.builder().setSecureSettings(mockSecureSettings).build();
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
|
||||
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore,
|
||||
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
|
@ -351,7 +355,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
MockSecureSettings mockSecureSettings = new MockSecureSettings();
|
||||
mockSecureSettings.setString("bootstrap.password", "foobar");
|
||||
Settings settings = Settings.builder().setSecureSettings(mockSecureSettings).build();
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(false);
|
||||
when(securityIndex.indexExists()).thenReturn(false);
|
||||
|
||||
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore,
|
||||
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
|
@ -369,7 +373,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
final String password = randomAlphaOfLengthBetween(8, 24);
|
||||
mockSecureSettings.setString("bootstrap.password", password);
|
||||
Settings settings = Settings.builder().setSecureSettings(mockSecureSettings).build();
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
|
||||
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore,
|
||||
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
|
@ -391,7 +395,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
final String password = randomAlphaOfLengthBetween(8, 24);
|
||||
mockSecureSettings.setString("bootstrap.password", password);
|
||||
Settings settings = Settings.builder().setSecureSettings(mockSecureSettings).build();
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(false);
|
||||
when(securityIndex.indexExists()).thenReturn(false);
|
||||
|
||||
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore,
|
||||
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.elasticsearch.xpack.core.security.user.User;
|
|||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -75,7 +76,9 @@ public class NativeRoleMappingStoreTests extends ESTestCase {
|
|||
|
||||
final Client client = mock(Client.class);
|
||||
final SecurityLifecycleService lifecycleService = mock(SecurityLifecycleService.class);
|
||||
when(lifecycleService.isSecurityIndexAvailable()).thenReturn(true);
|
||||
SecurityIndexManager securityIndex = mock(SecurityIndexManager.class);
|
||||
when(lifecycleService.securityIndex()).thenReturn(securityIndex);
|
||||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
|
||||
final NativeRoleMappingStore store = new NativeRoleMappingStore(Settings.EMPTY, client, lifecycleService) {
|
||||
@Override
|
||||
|
|
|
@ -21,7 +21,7 @@ import java.util.concurrent.CyclicBarrier;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class IndexLifecycleManagerIntegTests extends SecurityIntegTestCase {
|
||||
public class SecurityIndexManagerIntegTests extends SecurityIntegTestCase {
|
||||
|
||||
public void testConcurrentOperationsTryingToCreateSecurityIndexAndAlias() throws Exception {
|
||||
assertSecurityIndexActive();
|
|
@ -52,17 +52,17 @@ import org.hamcrest.Matchers;
|
|||
import org.junit.Before;
|
||||
|
||||
import static org.elasticsearch.cluster.routing.RecoverySource.StoreRecoverySource.EXISTING_STORE_INSTANCE;
|
||||
import static org.elasticsearch.xpack.security.support.IndexLifecycleManager.TEMPLATE_VERSION_PATTERN;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.TEMPLATE_VERSION_PATTERN;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class IndexLifecycleManagerTests extends ESTestCase {
|
||||
public class SecurityIndexManagerTests extends ESTestCase {
|
||||
|
||||
private static final ClusterName CLUSTER_NAME = new ClusterName("index-lifecycle-manager-tests");
|
||||
private static final ClusterState EMPTY_CLUSTER_STATE = new ClusterState.Builder(CLUSTER_NAME).build();
|
||||
public static final String INDEX_NAME = "IndexLifecycleManagerTests";
|
||||
private static final String TEMPLATE_NAME = "IndexLifecycleManagerTests-template";
|
||||
private IndexLifecycleManager manager;
|
||||
public static final String INDEX_NAME = "SecurityIndexManagerTests";
|
||||
private static final String TEMPLATE_NAME = "SecurityIndexManagerTests-template";
|
||||
private SecurityIndexManager manager;
|
||||
private Map<Action<?, ?, ?>, Map<ActionRequest, ActionListener<?>>> actions;
|
||||
|
||||
@Before
|
||||
|
@ -86,7 +86,7 @@ public class IndexLifecycleManagerTests extends ESTestCase {
|
|||
actions.put(action, map);
|
||||
}
|
||||
};
|
||||
manager = new IndexLifecycleManager(Settings.EMPTY, client, INDEX_NAME);
|
||||
manager = new SecurityIndexManager(Settings.EMPTY, client, INDEX_NAME);
|
||||
}
|
||||
|
||||
public void testIndexWithUpToDateMappingAndTemplate() throws IOException {
|
||||
|
@ -221,7 +221,7 @@ public class IndexLifecycleManagerTests extends ESTestCase {
|
|||
|
||||
// index doesn't exist and now exists with wrong format
|
||||
ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME,
|
||||
IndexLifecycleManager.INTERNAL_INDEX_FORMAT - 1);
|
||||
SecurityIndexManager.INTERNAL_INDEX_FORMAT - 1);
|
||||
markShardsAvailable(clusterStateBuilder);
|
||||
manager.clusterChanged(event(clusterStateBuilder));
|
||||
assertTrue(listenerCalled.get());
|
||||
|
@ -235,7 +235,7 @@ public class IndexLifecycleManagerTests extends ESTestCase {
|
|||
|
||||
listenerCalled.set(false);
|
||||
// index doesn't exist and now exists with correct format
|
||||
clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME, IndexLifecycleManager.INTERNAL_INDEX_FORMAT);
|
||||
clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME, SecurityIndexManager.INTERNAL_INDEX_FORMAT);
|
||||
markShardsAvailable(clusterStateBuilder);
|
||||
manager.clusterChanged(event(clusterStateBuilder));
|
||||
assertFalse(listenerCalled.get());
|
||||
|
@ -255,7 +255,7 @@ public class IndexLifecycleManagerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public static ClusterState.Builder createClusterState(String indexName, String templateName) throws IOException {
|
||||
return createClusterState(indexName, templateName, templateName, IndexLifecycleManager.INTERNAL_INDEX_FORMAT);
|
||||
return createClusterState(indexName, templateName, templateName, SecurityIndexManager.INTERNAL_INDEX_FORMAT);
|
||||
}
|
||||
|
||||
public static ClusterState.Builder createClusterState(String indexName, String templateName, int format) throws IOException {
|
|
@ -30,6 +30,7 @@ import org.elasticsearch.common.settings.SettingsFilter;
|
|||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.util.concurrent.EsExecutors;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.core.internal.io.IOUtils;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.env.NodeEnvironment;
|
||||
import org.elasticsearch.index.IndexModule;
|
||||
|
@ -216,6 +217,7 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin {
|
|||
|
||||
private static final Logger logger = Loggers.getLogger(Watcher.class);
|
||||
private WatcherIndexingListener listener;
|
||||
private HttpClient httpClient;
|
||||
|
||||
protected final Settings settings;
|
||||
protected final boolean transportClient;
|
||||
|
@ -266,7 +268,7 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin {
|
|||
// TODO: add more auth types, or remove this indirection
|
||||
HttpAuthRegistry httpAuthRegistry = new HttpAuthRegistry(httpAuthFactories);
|
||||
HttpRequestTemplate.Parser httpTemplateParser = new HttpRequestTemplate.Parser(httpAuthRegistry);
|
||||
final HttpClient httpClient = new HttpClient(settings, httpAuthRegistry, getSslService());
|
||||
httpClient = new HttpClient(settings, httpAuthRegistry, getSslService());
|
||||
|
||||
// notification
|
||||
EmailService emailService = new EmailService(settings, cryptoService, clusterService.getClusterSettings());
|
||||
|
@ -608,4 +610,9 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin {
|
|||
public List<ScriptContext> getContexts() {
|
||||
return Arrays.asList(Watcher.SCRIPT_SEARCH_CONTEXT, Watcher.SCRIPT_EXECUTABLE_CONTEXT, Watcher.SCRIPT_TEMPLATE_CONTEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
IOUtils.closeWhileHandlingException(httpClient);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
|
|||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
|
@ -56,9 +57,13 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class HttpClient extends AbstractComponent {
|
||||
public class HttpClient extends AbstractComponent implements Closeable {
|
||||
|
||||
private static final String SETTINGS_SSL_PREFIX = "xpack.http.ssl.";
|
||||
// picking a reasonable high value here to allow for setups with lots of watch executions or many http inputs/actions
|
||||
// this is also used as the value per route, if you are connecting to the same endpoint a lot, which is likely, when
|
||||
// you are querying a remote Elasticsearch cluster
|
||||
private static final int MAX_CONNECTIONS = 500;
|
||||
|
||||
private final HttpAuthRegistry httpAuthRegistry;
|
||||
private final CloseableHttpClient client;
|
||||
|
@ -84,6 +89,10 @@ public class HttpClient extends AbstractComponent {
|
|||
SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslService.sslSocketFactory(sslSettings), verifier);
|
||||
clientBuilder.setSSLSocketFactory(factory);
|
||||
|
||||
clientBuilder.evictExpiredConnections();
|
||||
clientBuilder.setMaxConnPerRoute(MAX_CONNECTIONS);
|
||||
clientBuilder.setMaxConnTotal(MAX_CONNECTIONS);
|
||||
|
||||
client = clientBuilder.build();
|
||||
}
|
||||
|
||||
|
@ -251,6 +260,11 @@ public class HttpClient extends AbstractComponent {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
client.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to have all HTTP methods except HEAD allow for an body, including GET
|
||||
*/
|
||||
|
|
|
@ -44,7 +44,6 @@ import org.joda.time.DateTime;
|
|||
import org.junit.Before;
|
||||
|
||||
import javax.mail.internet.AddressException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -219,10 +218,9 @@ public class WebhookActionTests extends ESTestCase {
|
|||
|
||||
public void testThatSelectingProxyWorks() throws Exception {
|
||||
Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
|
||||
HttpClient httpClient = new HttpClient(Settings.EMPTY, authRegistry,
|
||||
new SSLService(environment.settings(), environment));
|
||||
|
||||
try (MockWebServer proxyServer = new MockWebServer()) {
|
||||
try (HttpClient httpClient = new HttpClient(Settings.EMPTY, authRegistry,
|
||||
new SSLService(environment.settings(), environment)); MockWebServer proxyServer = new MockWebServer()) {
|
||||
proxyServer.start();
|
||||
proxyServer.enqueue(new MockResponse().setResponseCode(200).setBody("fullProxiedContent"));
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ public class HttpClientTests extends ESTestCase {
|
|||
@After
|
||||
public void shutdown() throws Exception {
|
||||
webServer.close();
|
||||
httpClient.close();
|
||||
}
|
||||
|
||||
public void testBasics() throws Exception {
|
||||
|
@ -184,17 +185,18 @@ public class HttpClientTests extends ESTestCase {
|
|||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
}
|
||||
httpClient = new HttpClient(settings, authRegistry, new SSLService(settings, environment));
|
||||
secureSettings = new MockSecureSettings();
|
||||
// We can't use the client created above for the server since it is only a truststore
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings2 = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", getDataPath("/org/elasticsearch/xpack/security/keystore/testnode.jks"))
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
|
||||
secureSettings = new MockSecureSettings();
|
||||
// We can't use the client created above for the server since it is only a truststore
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode");
|
||||
Settings settings2 = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path", getDataPath("/org/elasticsearch/xpack/security/keystore/testnode.jks"))
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
|
||||
TestsSSLService sslService = new TestsSSLService(settings2, environment);
|
||||
testSslMockWebserver(sslService.sslContext(), false);
|
||||
TestsSSLService sslService = new TestsSSLService(settings2, environment);
|
||||
testSslMockWebserver(client, sslService.sslContext(), false);
|
||||
}
|
||||
}
|
||||
|
||||
public void testHttpsDisableHostnameVerification() throws Exception {
|
||||
|
@ -217,18 +219,19 @@ public class HttpClientTests extends ESTestCase {
|
|||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
}
|
||||
httpClient = new HttpClient(settings, authRegistry, new SSLService(settings, environment));
|
||||
MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
// We can't use the client created above for the server since it only defines a truststore
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode-no-subjaltname");
|
||||
Settings settings2 = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path",
|
||||
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-no-subjaltname.jks"))
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
|
||||
MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
// We can't use the client created above for the server since it only defines a truststore
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode-no-subjaltname");
|
||||
Settings settings2 = Settings.builder()
|
||||
.put("xpack.ssl.keystore.path",
|
||||
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-no-subjaltname.jks"))
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
|
||||
TestsSSLService sslService = new TestsSSLService(settings2, environment);
|
||||
testSslMockWebserver(sslService.sslContext(), false);
|
||||
TestsSSLService sslService = new TestsSSLService(settings2, environment);
|
||||
testSslMockWebserver(client, sslService.sslContext(), false);
|
||||
}
|
||||
}
|
||||
|
||||
public void testHttpsClientAuth() throws Exception {
|
||||
|
@ -241,11 +244,12 @@ public class HttpClientTests extends ESTestCase {
|
|||
.build();
|
||||
|
||||
TestsSSLService sslService = new TestsSSLService(settings, environment);
|
||||
httpClient = new HttpClient(settings, authRegistry, sslService);
|
||||
testSslMockWebserver(sslService.sslContext(), true);
|
||||
try (HttpClient client = new HttpClient(settings, authRegistry, sslService)) {
|
||||
testSslMockWebserver(client, sslService.sslContext(), true);
|
||||
}
|
||||
}
|
||||
|
||||
private void testSslMockWebserver(SSLContext sslContext, boolean needClientAuth) throws IOException {
|
||||
private void testSslMockWebserver(HttpClient client, SSLContext sslContext, boolean needClientAuth) throws IOException {
|
||||
try (MockWebServer mockWebServer = new MockWebServer(sslContext, needClientAuth)) {
|
||||
mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody("body"));
|
||||
mockWebServer.start();
|
||||
|
@ -253,7 +257,7 @@ public class HttpClientTests extends ESTestCase {
|
|||
HttpRequest.Builder request = HttpRequest.builder("localhost", mockWebServer.getPort())
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/test");
|
||||
HttpResponse response = httpClient.execute(request.build());
|
||||
HttpResponse response = client.execute(request.build());
|
||||
assertThat(response.status(), equalTo(200));
|
||||
assertThat(response.body().utf8ToString(), equalTo("body"));
|
||||
|
||||
|
@ -288,14 +292,14 @@ public class HttpClientTests extends ESTestCase {
|
|||
|
||||
@Network
|
||||
public void testHttpsWithoutTruststore() throws Exception {
|
||||
HttpClient httpClient = new HttpClient(Settings.EMPTY, authRegistry, new SSLService(Settings.EMPTY, environment));
|
||||
|
||||
// Known server with a valid cert from a commercial CA
|
||||
HttpRequest.Builder request = HttpRequest.builder("www.elastic.co", 443).scheme(Scheme.HTTPS);
|
||||
HttpResponse response = httpClient.execute(request.build());
|
||||
assertThat(response.status(), equalTo(200));
|
||||
assertThat(response.hasContent(), is(true));
|
||||
assertThat(response.body(), notNullValue());
|
||||
try (HttpClient client = new HttpClient(Settings.EMPTY, authRegistry, new SSLService(Settings.EMPTY, environment))) {
|
||||
// Known server with a valid cert from a commercial CA
|
||||
HttpRequest.Builder request = HttpRequest.builder("www.elastic.co", 443).scheme(Scheme.HTTPS);
|
||||
HttpResponse response = client.execute(request.build());
|
||||
assertThat(response.status(), equalTo(200));
|
||||
assertThat(response.hasContent(), is(true));
|
||||
assertThat(response.body(), notNullValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void testThatProxyCanBeConfigured() throws Exception {
|
||||
|
@ -307,15 +311,16 @@ public class HttpClientTests extends ESTestCase {
|
|||
.put(HttpSettings.PROXY_HOST.getKey(), "localhost")
|
||||
.put(HttpSettings.PROXY_PORT.getKey(), proxyServer.getPort())
|
||||
.build();
|
||||
HttpClient httpClient = new HttpClient(settings, authRegistry, new SSLService(settings, environment));
|
||||
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort())
|
||||
.method(HttpMethod.GET)
|
||||
.path("/");
|
||||
|
||||
HttpResponse response = httpClient.execute(requestBuilder.build());
|
||||
assertThat(response.status(), equalTo(200));
|
||||
assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent"));
|
||||
try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
|
||||
HttpResponse response = client.execute(requestBuilder.build());
|
||||
assertThat(response.status(), equalTo(200));
|
||||
assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent"));
|
||||
}
|
||||
|
||||
// ensure we hit the proxyServer and not the webserver
|
||||
assertThat(webServer.requests(), hasSize(0));
|
||||
|
@ -386,16 +391,16 @@ public class HttpClientTests extends ESTestCase {
|
|||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
|
||||
HttpClient httpClient = new HttpClient(settings, authRegistry, new SSLService(settings, environment));
|
||||
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort())
|
||||
.method(HttpMethod.GET)
|
||||
.scheme(Scheme.HTTP)
|
||||
.path("/");
|
||||
|
||||
HttpResponse response = httpClient.execute(requestBuilder.build());
|
||||
assertThat(response.status(), equalTo(200));
|
||||
assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent"));
|
||||
try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
|
||||
HttpResponse response = client.execute(requestBuilder.build());
|
||||
assertThat(response.status(), equalTo(200));
|
||||
assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent"));
|
||||
}
|
||||
|
||||
// ensure we hit the proxyServer and not the webserver
|
||||
assertThat(webServer.requests(), hasSize(0));
|
||||
|
@ -413,16 +418,17 @@ public class HttpClientTests extends ESTestCase {
|
|||
.put(HttpSettings.PROXY_PORT.getKey(), proxyServer.getPort() + 1)
|
||||
.put(HttpSettings.PROXY_HOST.getKey(), "https")
|
||||
.build();
|
||||
HttpClient httpClient = new HttpClient(settings, authRegistry, new SSLService(settings, environment));
|
||||
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort())
|
||||
.method(HttpMethod.GET)
|
||||
.proxy(new HttpProxy("localhost", proxyServer.getPort(), Scheme.HTTP))
|
||||
.path("/");
|
||||
|
||||
HttpResponse response = httpClient.execute(requestBuilder.build());
|
||||
assertThat(response.status(), equalTo(200));
|
||||
assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent"));
|
||||
try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
|
||||
HttpResponse response = client.execute(requestBuilder.build());
|
||||
assertThat(response.status(), equalTo(200));
|
||||
assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent"));
|
||||
}
|
||||
|
||||
// ensure we hit the proxyServer and not the webserver
|
||||
assertThat(webServer.requests(), hasSize(0));
|
||||
|
@ -535,12 +541,13 @@ public class HttpClientTests extends ESTestCase {
|
|||
Settings settings = Settings.builder()
|
||||
.put(HttpSettings.MAX_HTTP_RESPONSE_SIZE.getKey(), new ByteSizeValue(randomBytesLength - 1, ByteSizeUnit.BYTES))
|
||||
.build();
|
||||
HttpClient httpClient = new HttpClient(settings, authRegistry, new SSLService(environment.settings(), environment));
|
||||
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort()).method(HttpMethod.GET).path("/");
|
||||
|
||||
IOException e = expectThrows(IOException.class, () -> httpClient.execute(requestBuilder.build()));
|
||||
assertThat(e.getMessage(), startsWith("Maximum limit of"));
|
||||
try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(environment.settings(), environment))) {
|
||||
IOException e = expectThrows(IOException.class, () -> client.execute(requestBuilder.build()));
|
||||
assertThat(e.getMessage(), startsWith("Maximum limit of"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testThatGetRedirectIsFollowed() throws Exception {
|
||||
|
|
|
@ -40,66 +40,69 @@ public class HttpReadTimeoutTests extends ESTestCase {
|
|||
|
||||
public void testDefaultTimeout() throws Exception {
|
||||
Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
|
||||
HttpClient httpClient = new HttpClient(Settings.EMPTY, mock(HttpAuthRegistry.class),
|
||||
new SSLService(environment.settings(), environment));
|
||||
|
||||
HttpRequest request = HttpRequest.builder("localhost", webServer.getPort())
|
||||
.method(HttpMethod.POST)
|
||||
.path("/")
|
||||
.build();
|
||||
|
||||
long start = System.nanoTime();
|
||||
expectThrows(SocketTimeoutException.class, () -> httpClient.execute(request));
|
||||
TimeValue timeout = TimeValue.timeValueNanos(System.nanoTime() - start);
|
||||
logger.info("http connection timed out after {}", timeout);
|
||||
try (HttpClient httpClient = new HttpClient(Settings.EMPTY, mock(HttpAuthRegistry.class),
|
||||
new SSLService(environment.settings(), environment))) {
|
||||
long start = System.nanoTime();
|
||||
|
||||
// it's supposed to be 10, but we'll give it an error margin of 2 seconds
|
||||
assertThat(timeout.seconds(), greaterThan(8L));
|
||||
assertThat(timeout.seconds(), lessThan(12L));
|
||||
expectThrows(SocketTimeoutException.class, () -> httpClient.execute(request));
|
||||
TimeValue timeout = TimeValue.timeValueNanos(System.nanoTime() - start);
|
||||
logger.info("http connection timed out after {}", timeout);
|
||||
|
||||
// it's supposed to be 10, but we'll give it an error margin of 2 seconds
|
||||
assertThat(timeout.seconds(), greaterThan(8L));
|
||||
assertThat(timeout.seconds(), lessThan(12L));
|
||||
}
|
||||
}
|
||||
|
||||
public void testDefaultTimeoutCustom() throws Exception {
|
||||
Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
|
||||
|
||||
HttpClient httpClient = new HttpClient(Settings.builder()
|
||||
.put("xpack.http.default_read_timeout", "3s").build()
|
||||
, mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment));
|
||||
|
||||
HttpRequest request = HttpRequest.builder("localhost", webServer.getPort())
|
||||
.method(HttpMethod.POST)
|
||||
.path("/")
|
||||
.build();
|
||||
|
||||
long start = System.nanoTime();
|
||||
expectThrows(SocketTimeoutException.class, () -> httpClient.execute(request));
|
||||
TimeValue timeout = TimeValue.timeValueNanos(System.nanoTime() - start);
|
||||
logger.info("http connection timed out after {}", timeout);
|
||||
try (HttpClient httpClient = new HttpClient(Settings.builder()
|
||||
.put("xpack.http.default_read_timeout", "3s").build()
|
||||
, mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment))) {
|
||||
|
||||
// it's supposed to be 3, but we'll give it an error margin of 2 seconds
|
||||
assertThat(timeout.seconds(), greaterThan(1L));
|
||||
assertThat(timeout.seconds(), lessThan(5L));
|
||||
long start = System.nanoTime();
|
||||
expectThrows(SocketTimeoutException.class, () -> httpClient.execute(request));
|
||||
TimeValue timeout = TimeValue.timeValueNanos(System.nanoTime() - start);
|
||||
logger.info("http connection timed out after {}", timeout);
|
||||
|
||||
// it's supposed to be 3, but we'll give it an error margin of 2 seconds
|
||||
assertThat(timeout.seconds(), greaterThan(1L));
|
||||
assertThat(timeout.seconds(), lessThan(5L));
|
||||
}
|
||||
}
|
||||
|
||||
public void testTimeoutCustomPerRequest() throws Exception {
|
||||
Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
|
||||
|
||||
HttpClient httpClient = new HttpClient(Settings.builder()
|
||||
.put("xpack.http.default_read_timeout", "10s").build()
|
||||
, mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment));
|
||||
|
||||
HttpRequest request = HttpRequest.builder("localhost", webServer.getPort())
|
||||
.readTimeout(TimeValue.timeValueSeconds(3))
|
||||
.method(HttpMethod.POST)
|
||||
.path("/")
|
||||
.build();
|
||||
|
||||
long start = System.nanoTime();
|
||||
expectThrows(SocketTimeoutException.class, () -> httpClient.execute(request));
|
||||
TimeValue timeout = TimeValue.timeValueNanos(System.nanoTime() - start);
|
||||
logger.info("http connection timed out after {}", timeout);
|
||||
try (HttpClient httpClient = new HttpClient(Settings.builder()
|
||||
.put("xpack.http.default_read_timeout", "10s").build()
|
||||
, mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment))) {
|
||||
|
||||
// it's supposed to be 3, but we'll give it an error margin of 2 seconds
|
||||
assertThat(timeout.seconds(), greaterThan(1L));
|
||||
assertThat(timeout.seconds(), lessThan(5L));
|
||||
long start = System.nanoTime();
|
||||
expectThrows(SocketTimeoutException.class, () -> httpClient.execute(request));
|
||||
TimeValue timeout = TimeValue.timeValueNanos(System.nanoTime() - start);
|
||||
logger.info("http connection timed out after {}", timeout);
|
||||
|
||||
// it's supposed to be 3, but we'll give it an error margin of 2 seconds
|
||||
assertThat(timeout.seconds(), greaterThan(1L));
|
||||
assertThat(timeout.seconds(), lessThan(5L));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.elasticsearch.test.rest.ESRestTestCase;
|
|||
import org.elasticsearch.xpack.core.monitoring.exporter.MonitoringTemplateUtils;
|
||||
import org.elasticsearch.xpack.core.watcher.client.WatchSourceBuilder;
|
||||
import org.elasticsearch.xpack.core.watcher.support.xcontent.ObjectPath;
|
||||
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.elasticsearch.xpack.test.rest.XPackRestTestHelper;
|
||||
import org.elasticsearch.xpack.watcher.actions.logging.LoggingAction;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
|
||||
|
@ -138,7 +138,7 @@ public class FullClusterRestartIT extends ESRestTestCase {
|
|||
logger.info("settings map {}", settingsMap);
|
||||
if (settingsMap.containsKey("index")) {
|
||||
int format = Integer.parseInt(String.valueOf(((Map<String, Object>)settingsMap.get("index")).get("format")));
|
||||
needsUpgrade = format == IndexLifecycleManager.INTERNAL_INDEX_FORMAT ? false : true;
|
||||
needsUpgrade = format == SecurityIndexManager.INTERNAL_INDEX_FORMAT ? false : true;
|
||||
} else {
|
||||
needsUpgrade = true;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.upgrades;
|
|||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.TimeUnits;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
|
@ -29,6 +30,7 @@ import static java.util.Collections.singletonMap;
|
|||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
@TimeoutSuite(millis = 5 * TimeUnits.MINUTE) // to account for slow as hell VMs
|
||||
@LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/30456")
|
||||
public class UpgradeClusterClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue