Remove shard level injector usage
This commit catches up with master which removed the shard level injector and changed the logic how the SearcherWrapper works and is installed. The way we now install it is via a package private onModule(IndexModule) call. There is no public API for this anymore. The wrapper also doesn't need to watch the IndexShards state since now it will only be used when the shard is STARTED or RECOVERED. Original commit: elastic/x-pack-elasticsearch@42b9eeef3d
This commit is contained in:
parent
01db047053
commit
b7ca362df5
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.index;
|
||||||
|
|
||||||
|
import org.elasticsearch.shield.authz.accesscontrol.ShieldIndexSearcherWrapper;
|
||||||
|
|
||||||
|
public class SearcherWrapperInstaller {
|
||||||
|
|
||||||
|
public static void install(IndexModule module) {
|
||||||
|
module.indexSearcherWrapper = ShieldIndexSearcherWrapper.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.common.inject.Module;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.http.HttpServerModule;
|
import org.elasticsearch.http.HttpServerModule;
|
||||||
|
import org.elasticsearch.index.IndexModule;
|
||||||
import org.elasticsearch.index.cache.IndexCacheModule;
|
import org.elasticsearch.index.cache.IndexCacheModule;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
import org.elasticsearch.rest.RestModule;
|
import org.elasticsearch.rest.RestModule;
|
||||||
|
@ -29,8 +30,9 @@ import org.elasticsearch.shield.authc.Realms;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||||
import org.elasticsearch.shield.authz.AuthorizationModule;
|
import org.elasticsearch.shield.authz.AuthorizationModule;
|
||||||
import org.elasticsearch.shield.authz.accesscontrol.AccessControlShardModule;
|
import org.elasticsearch.index.SearcherWrapperInstaller;
|
||||||
import org.elasticsearch.shield.authz.accesscontrol.OptOutQueryCache;
|
import org.elasticsearch.shield.authz.accesscontrol.OptOutQueryCache;
|
||||||
|
import org.elasticsearch.shield.authz.accesscontrol.ShieldIndexSearcherWrapper;
|
||||||
import org.elasticsearch.shield.authz.store.FileRolesStore;
|
import org.elasticsearch.shield.authz.store.FileRolesStore;
|
||||||
import org.elasticsearch.shield.crypto.CryptoModule;
|
import org.elasticsearch.shield.crypto.CryptoModule;
|
||||||
import org.elasticsearch.shield.crypto.InternalCryptoService;
|
import org.elasticsearch.shield.crypto.InternalCryptoService;
|
||||||
|
@ -115,20 +117,11 @@ public class ShieldPlugin extends Plugin {
|
||||||
public Collection<Module> indexModules(Settings settings) {
|
public Collection<Module> indexModules(Settings settings) {
|
||||||
if (enabled && clientMode == false) {
|
if (enabled && clientMode == false) {
|
||||||
failIfShieldQueryCacheIsNotActive(settings, false);
|
failIfShieldQueryCacheIsNotActive(settings, false);
|
||||||
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Module> shardModules(Settings settings) {
|
|
||||||
if (enabled && clientMode == false) {
|
|
||||||
failIfShieldQueryCacheIsNotActive(settings, false);
|
|
||||||
return Collections.<Module>singletonList(new AccessControlShardModule(settings));
|
|
||||||
} else {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||||
if (enabled && clientMode == false) {
|
if (enabled && clientMode == false) {
|
||||||
|
@ -158,6 +151,13 @@ public class ShieldPlugin extends Plugin {
|
||||||
clusterDynamicSettingsModule.registerClusterDynamicSetting(IPFilter.IP_FILTER_ENABLED_HTTP_SETTING, Validator.EMPTY);
|
clusterDynamicSettingsModule.registerClusterDynamicSetting(IPFilter.IP_FILTER_ENABLED_HTTP_SETTING, Validator.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onModule(IndexModule module) {
|
||||||
|
if (enabled == false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SearcherWrapperInstaller.install(module);
|
||||||
|
}
|
||||||
|
|
||||||
public void onModule(ActionModule module) {
|
public void onModule(ActionModule module) {
|
||||||
if (enabled == false) {
|
if (enabled == false) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License;
|
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
|
||||||
*/
|
|
||||||
package org.elasticsearch.shield.authz.accesscontrol;
|
|
||||||
|
|
||||||
import org.elasticsearch.common.inject.multibindings.Multibinder;
|
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.index.engine.IndexSearcherWrapper;
|
|
||||||
import org.elasticsearch.shield.support.AbstractShieldModule;
|
|
||||||
|
|
||||||
public class AccessControlShardModule extends AbstractShieldModule.Node {
|
|
||||||
|
|
||||||
public AccessControlShardModule(Settings settings) {
|
|
||||||
super(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureNode() {
|
|
||||||
Multibinder<IndexSearcherWrapper> multibinder
|
|
||||||
= Multibinder.newSetBinder(binder(), IndexSearcherWrapper.class);
|
|
||||||
multibinder.addBinding().to(ShieldIndexSearcherWrapper.class);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,24 +12,22 @@ import org.apache.lucene.util.*;
|
||||||
import org.apache.lucene.util.BitSet;
|
import org.apache.lucene.util.BitSet;
|
||||||
import org.elasticsearch.ExceptionsHelper;
|
import org.elasticsearch.ExceptionsHelper;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
|
import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
|
||||||
import org.elasticsearch.index.engine.EngineConfig;
|
import org.elasticsearch.index.engine.EngineConfig;
|
||||||
import org.elasticsearch.index.engine.EngineException;
|
import org.elasticsearch.index.engine.EngineException;
|
||||||
import org.elasticsearch.index.engine.IndexSearcherWrapper;
|
|
||||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||||
import org.elasticsearch.index.mapper.MapperService;
|
import org.elasticsearch.index.mapper.MapperService;
|
||||||
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
|
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
|
||||||
import org.elasticsearch.index.query.IndexQueryParserService;
|
import org.elasticsearch.index.query.IndexQueryParserService;
|
||||||
import org.elasticsearch.index.query.ParsedQuery;
|
import org.elasticsearch.index.query.ParsedQuery;
|
||||||
import org.elasticsearch.index.settings.IndexSettings;
|
import org.elasticsearch.index.settings.IndexSettings;
|
||||||
import org.elasticsearch.index.shard.AbstractIndexShardComponent;
|
import org.elasticsearch.index.shard.IndexSearcherWrapper;
|
||||||
import org.elasticsearch.index.shard.IndexShard;
|
|
||||||
import org.elasticsearch.index.shard.ShardId;
|
import org.elasticsearch.index.shard.ShardId;
|
||||||
import org.elasticsearch.index.shard.ShardUtils;
|
import org.elasticsearch.index.shard.ShardUtils;
|
||||||
import org.elasticsearch.indices.IndicesLifecycle;
|
|
||||||
import org.elasticsearch.shield.authz.InternalAuthorizationService;
|
import org.elasticsearch.shield.authz.InternalAuthorizationService;
|
||||||
import org.elasticsearch.shield.authz.accesscontrol.DocumentSubsetReader.DocumentSubsetDirectoryReader;
|
import org.elasticsearch.shield.authz.accesscontrol.DocumentSubsetReader.DocumentSubsetDirectoryReader;
|
||||||
import org.elasticsearch.shield.support.Exceptions;
|
import org.elasticsearch.shield.support.Exceptions;
|
||||||
|
@ -50,22 +48,19 @@ import static org.apache.lucene.search.BooleanClause.Occur.FILTER;
|
||||||
* Document level security is enabled by wrapping the original {@link DirectoryReader} in a {@link DocumentSubsetReader}
|
* Document level security is enabled by wrapping the original {@link DirectoryReader} in a {@link DocumentSubsetReader}
|
||||||
* instance.
|
* instance.
|
||||||
*/
|
*/
|
||||||
public final class ShieldIndexSearcherWrapper extends AbstractIndexShardComponent implements IndexSearcherWrapper {
|
public final class ShieldIndexSearcherWrapper extends AbstractComponent implements IndexSearcherWrapper {
|
||||||
|
|
||||||
private final MapperService mapperService;
|
private final MapperService mapperService;
|
||||||
private final Set<String> allowedMetaFields;
|
private final Set<String> allowedMetaFields;
|
||||||
private final IndexQueryParserService parserService;
|
private final IndexQueryParserService parserService;
|
||||||
private final BitsetFilterCache bitsetFilterCache;
|
private final BitsetFilterCache bitsetFilterCache;
|
||||||
|
|
||||||
private volatile boolean shardStarted = false;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ShieldIndexSearcherWrapper(ShardId shardId, @IndexSettings Settings indexSettings, IndexQueryParserService parserService, IndicesLifecycle indicesLifecycle, MapperService mapperService, BitsetFilterCache bitsetFilterCache) {
|
public ShieldIndexSearcherWrapper(@IndexSettings Settings indexSettings, IndexQueryParserService parserService, MapperService mapperService, BitsetFilterCache bitsetFilterCache) {
|
||||||
super(shardId, indexSettings);
|
super(indexSettings);
|
||||||
this.mapperService = mapperService;
|
this.mapperService = mapperService;
|
||||||
this.parserService = parserService;
|
this.parserService = parserService;
|
||||||
this.bitsetFilterCache = bitsetFilterCache;
|
this.bitsetFilterCache = bitsetFilterCache;
|
||||||
indicesLifecycle.addListener(new ShardLifecycleListener());
|
|
||||||
|
|
||||||
Set<String> allowedMetaFields = new HashSet<>();
|
Set<String> allowedMetaFields = new HashSet<>();
|
||||||
allowedMetaFields.addAll(Arrays.asList(MapperService.getAllMetaFields()));
|
allowedMetaFields.addAll(Arrays.asList(MapperService.getAllMetaFields()));
|
||||||
|
@ -82,15 +77,8 @@ public final class ShieldIndexSearcherWrapper extends AbstractIndexShardComponen
|
||||||
try {
|
try {
|
||||||
RequestContext context = RequestContext.current();
|
RequestContext context = RequestContext.current();
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
if (shardStarted == false) {
|
logger.debug("couldn't locate the current request, field level security will only allow meta fields");
|
||||||
// The shard this index searcher wrapper has been created for hasn't started yet,
|
return FieldSubsetReader.wrap(reader, allowedMetaFields);
|
||||||
// We may load some initial stuff like for example previous stored percolator queries and recovery,
|
|
||||||
// so for this reason we should provide access to all fields:
|
|
||||||
return reader;
|
|
||||||
} else {
|
|
||||||
logger.debug("couldn't locate the current request, field level security will only allow meta fields");
|
|
||||||
return FieldSubsetReader.wrap(reader, allowedMetaFields);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IndicesAccessControl indicesAccessControl = context.getRequest().getFromContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
IndicesAccessControl indicesAccessControl = context.getRequest().getFromContext(InternalAuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||||
|
@ -207,16 +195,6 @@ public final class ShieldIndexSearcherWrapper extends AbstractIndexShardComponen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ShardLifecycleListener extends IndicesLifecycle.Listener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterIndexShardPostRecovery(IndexShard indexShard) {
|
|
||||||
if (shardId.equals(indexShard.shardId())) {
|
|
||||||
shardStarted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void intersectScorerAndRoleBits(Scorer scorer, SparseFixedBitSet roleBits, LeafCollector collector, Bits acceptDocs) throws IOException {
|
static void intersectScorerAndRoleBits(Scorer scorer, SparseFixedBitSet roleBits, LeafCollector collector, Bits acceptDocs) throws IOException {
|
||||||
// ConjunctionDISI uses the DocIdSetIterator#cost() to order the iterators, so if roleBits has the lowest cardinality it should be used first:
|
// ConjunctionDISI uses the DocIdSetIterator#cost() to order the iterators, so if roleBits has the lowest cardinality it should be used first:
|
||||||
DocIdSetIterator iterator = ConjunctionDISI.intersect(Arrays.asList(new BitSetIterator(roleBits, roleBits.approximateCardinality()), scorer));
|
DocIdSetIterator iterator = ConjunctionDISI.intersect(Arrays.asList(new BitSetIterator(roleBits, roleBits.approximateCardinality()), scorer));
|
||||||
|
|
|
@ -11,27 +11,15 @@ import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.document.StringField;
|
import org.apache.lucene.document.StringField;
|
||||||
import org.apache.lucene.index.*;
|
import org.apache.lucene.index.*;
|
||||||
import org.apache.lucene.search.*;
|
import org.apache.lucene.search.*;
|
||||||
import org.apache.lucene.search.join.BitDocIdSetFilter;
|
|
||||||
import org.apache.lucene.search.join.BitSetProducer;
|
import org.apache.lucene.search.join.BitSetProducer;
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.util.BitDocIdSet;
|
|
||||||
import org.apache.lucene.util.BitSet;
|
import org.apache.lucene.util.BitSet;
|
||||||
import org.apache.lucene.util.Bits;
|
import org.apache.lucene.util.Bits;
|
||||||
import org.apache.lucene.util.SparseFixedBitSet;
|
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.index.Index;
|
|
||||||
import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
|
import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
|
||||||
import org.elasticsearch.index.shard.ShardId;
|
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
|
||||||
import org.mockito.Matchers;
|
import org.mockito.Matchers;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
|
||||||
import org.mockito.stubbing.Answer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class ShieldIndexSearcherWrapperIntegrationTests extends ESTestCase {
|
||||||
|
|
||||||
public void testDLS() throws Exception {
|
public void testDLS() throws Exception {
|
||||||
ShardId shardId = new ShardId("_index", 0);
|
ShardId shardId = new ShardId("_index", 0);
|
||||||
EngineConfig engineConfig = new EngineConfig(shardId, null, null, Settings.EMPTY, null, null, null, null, null, null, null, null, null, null, null, QueryCachingPolicy.ALWAYS_CACHE, null, null); // can't mock...
|
EngineConfig engineConfig = new EngineConfig(shardId, null, null, Settings.EMPTY, null, null, null, null, null, null, null, null, null, null, null, QueryCachingPolicy.ALWAYS_CACHE, null); // can't mock...
|
||||||
|
|
||||||
MapperService mapperService = mock(MapperService.class);
|
MapperService mapperService = mock(MapperService.class);
|
||||||
when(mapperService.docMappers(anyBoolean())).thenReturn(Collections.emptyList());
|
when(mapperService.docMappers(anyBoolean())).thenReturn(Collections.emptyList());
|
||||||
|
@ -102,7 +102,7 @@ public class ShieldIndexSearcherWrapperIntegrationTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ShieldIndexSearcherWrapper wrapper = new ShieldIndexSearcherWrapper(
|
ShieldIndexSearcherWrapper wrapper = new ShieldIndexSearcherWrapper(
|
||||||
shardId, Settings.EMPTY, parserService, indicesLifecycle, mapperService, bitsetFilterCache
|
Settings.EMPTY, parserService, mapperService, bitsetFilterCache
|
||||||
);
|
);
|
||||||
|
|
||||||
Directory directory = newDirectory();
|
Directory directory = newDirectory();
|
||||||
|
|
|
@ -86,11 +86,9 @@ public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
||||||
mapperService = new MapperService(index, settings, analysisService, similarityLookupService, scriptService);
|
mapperService = new MapperService(index, settings, analysisService, similarityLookupService, scriptService);
|
||||||
|
|
||||||
shardId = new ShardId(index, 0);
|
shardId = new ShardId(index, 0);
|
||||||
InternalIndicesLifecycle indicesLifecycle = new InternalIndicesLifecycle(settings);
|
shieldIndexSearcherWrapper = new ShieldIndexSearcherWrapper(settings, null, mapperService, null);
|
||||||
shieldIndexSearcherWrapper = new ShieldIndexSearcherWrapper(shardId, settings, null, indicesLifecycle, mapperService, null);
|
|
||||||
IndexShard indexShard = mock(IndexShard.class);
|
IndexShard indexShard = mock(IndexShard.class);
|
||||||
when(indexShard.shardId()).thenReturn(shardId);
|
when(indexShard.shardId()).thenReturn(shardId);
|
||||||
indicesLifecycle.afterIndexShardPostRecovery(indexShard);
|
|
||||||
|
|
||||||
request = new TransportRequest.Empty();
|
request = new TransportRequest.Empty();
|
||||||
RequestContext.setCurrent(new RequestContext(request));
|
RequestContext.setCurrent(new RequestContext(request));
|
||||||
|
@ -227,7 +225,7 @@ public class ShieldIndexSearcherWrapperUnitTests extends ESTestCase {
|
||||||
|
|
||||||
public void testDelegateSimilarity() throws Exception {
|
public void testDelegateSimilarity() throws Exception {
|
||||||
ShardId shardId = new ShardId("_index", 0);
|
ShardId shardId = new ShardId("_index", 0);
|
||||||
EngineConfig engineConfig = new EngineConfig(shardId, null, null, Settings.EMPTY, null, null, null, null, null, null, new BM25Similarity(), null, null, null, new NoneQueryCache(shardId.index(), Settings.EMPTY), QueryCachingPolicy.ALWAYS_CACHE, null, null); // can't mock...
|
EngineConfig engineConfig = new EngineConfig(shardId, null, null, Settings.EMPTY, null, null, null, null, null, null, new BM25Similarity(), null, null, null, new NoneQueryCache(shardId.index(), Settings.EMPTY), QueryCachingPolicy.ALWAYS_CACHE, null); // can't mock...
|
||||||
|
|
||||||
BitsetFilterCache bitsetFilterCache = mock(BitsetFilterCache.class);
|
BitsetFilterCache bitsetFilterCache = mock(BitsetFilterCache.class);
|
||||||
DirectoryReader directoryReader = DocumentSubsetReader.wrap(esIn, bitsetFilterCache, new MatchAllDocsQuery());
|
DirectoryReader directoryReader = DocumentSubsetReader.wrap(esIn, bitsetFilterCache, new MatchAllDocsQuery());
|
||||||
|
|
Loading…
Reference in New Issue