Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.floragunn.searchguard.SearchGuardPlugin Maven / Gradle / Ivy
Go to download
Provide access control related features for Elasticsearch 6
/*
* Copyright 2015-2017 floragunn GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.floragunn.searchguard;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.PosixFilePermission;
import java.security.AccessController;
import java.security.MessageDigest;
import java.security.PrivilegedAction;
import java.security.Security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.lucene.search.QueryCachingPolicy;
import org.apache.lucene.search.Weight;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.SpecialPermission;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.search.SearchScrollAction;
import org.elasticsearch.action.support.ActionFilter;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.component.Lifecycle.State;
import org.elasticsearch.common.component.LifecycleComponent;
import org.elasticsearch.common.component.LifecycleListener;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.IndexScopedSettings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsFilter;
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.env.Environment;
import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.http.HttpServerTransport.Dispatcher;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexModule;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.cache.query.QueryCache;
import org.elasticsearch.index.shard.IndexSearcherWrapper;
import org.elasticsearch.index.shard.SearchOperationListener;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.plugins.ClusterPlugin;
import org.elasticsearch.plugins.MapperPlugin;
import org.elasticsearch.repositories.RepositoriesService;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestHandler;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.internal.ScrollContext;
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.RemoteClusterService;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.Transport.Connection;
import org.elasticsearch.transport.TransportChannel;
import org.elasticsearch.transport.TransportInterceptor;
import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.transport.TransportRequestHandler;
import org.elasticsearch.transport.TransportRequestOptions;
import org.elasticsearch.transport.TransportResponse;
import org.elasticsearch.transport.TransportResponseHandler;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.watcher.ResourceWatcherService;
import com.floragunn.searchguard.action.configupdate.ConfigUpdateAction;
import com.floragunn.searchguard.action.configupdate.TransportConfigUpdateAction;
import com.floragunn.searchguard.action.licenseinfo.LicenseInfoAction;
import com.floragunn.searchguard.action.licenseinfo.TransportLicenseInfoAction;
import com.floragunn.searchguard.action.whoami.TransportWhoAmIAction;
import com.floragunn.searchguard.action.whoami.WhoAmIAction;
import com.floragunn.searchguard.auditlog.AuditLog;
import com.floragunn.searchguard.auditlog.AuditLog.Origin;
import com.floragunn.searchguard.auditlog.AuditLogSslExceptionHandler;
import com.floragunn.searchguard.auditlog.NullAuditLog;
import com.floragunn.searchguard.auth.BackendRegistry;
import com.floragunn.searchguard.auth.internal.InternalAuthenticationBackend;
import com.floragunn.searchguard.compliance.ComplianceConfig;
import com.floragunn.searchguard.compliance.ComplianceIndexingOperationListener;
import com.floragunn.searchguard.configuration.ActionGroupHolder;
import com.floragunn.searchguard.configuration.AdminDNs;
import com.floragunn.searchguard.configuration.ClusterInfoHolder;
import com.floragunn.searchguard.configuration.CompatConfig;
import com.floragunn.searchguard.configuration.ConfigurationChangeListener;
import com.floragunn.searchguard.configuration.DlsFlsRequestValve;
import com.floragunn.searchguard.configuration.IndexBaseConfigurationRepository;
import com.floragunn.searchguard.configuration.SearchGuardIndexSearcherWrapper;
import com.floragunn.searchguard.filter.SearchGuardFilter;
import com.floragunn.searchguard.filter.SearchGuardRestFilter;
import com.floragunn.searchguard.http.SearchGuardHttpServerTransport;
import com.floragunn.searchguard.http.SearchGuardNonSslHttpServerTransport;
import com.floragunn.searchguard.http.XFFResolver;
import com.floragunn.searchguard.privileges.PrivilegesEvaluator;
import com.floragunn.searchguard.privileges.PrivilegesInterceptor;
import com.floragunn.searchguard.resolver.IndexResolverReplacer;
import com.floragunn.searchguard.rest.KibanaInfoAction;
import com.floragunn.searchguard.rest.SearchGuardHealthAction;
import com.floragunn.searchguard.rest.SearchGuardInfoAction;
import com.floragunn.searchguard.rest.SearchGuardLicenseAction;
import com.floragunn.searchguard.rest.TenantInfoAction;
import com.floragunn.searchguard.ssl.SearchGuardSSLPlugin;
import com.floragunn.searchguard.ssl.SslExceptionHandler;
import com.floragunn.searchguard.ssl.http.netty.ValidatingDispatcher;
import com.floragunn.searchguard.ssl.transport.SearchGuardSSLNettyTransport;
import com.floragunn.searchguard.ssl.util.SSLConfigConstants;
import com.floragunn.searchguard.support.ConfigConstants;
import com.floragunn.searchguard.support.HeaderHelper;
import com.floragunn.searchguard.support.ModuleInfo;
import com.floragunn.searchguard.support.ReflectionHelper;
import com.floragunn.searchguard.support.SgUtils;
import com.floragunn.searchguard.support.WildcardMatcher;
import com.floragunn.searchguard.transport.DefaultInterClusterRequestEvaluator;
import com.floragunn.searchguard.transport.InterClusterRequestEvaluator;
import com.floragunn.searchguard.transport.SearchGuardInterceptor;
import com.floragunn.searchguard.user.User;
import com.google.common.collect.Lists;
public final class SearchGuardPlugin extends SearchGuardSSLPlugin implements ClusterPlugin, MapperPlugin {
private static final String KEYWORD = ".keyword";
private final boolean tribeNodeClient;
private final boolean dlsFlsAvailable;
private final Constructor> dlsFlsConstructor;
private volatile SearchGuardRestFilter sgRestHandler;
private volatile SearchGuardInterceptor sgi;
private volatile PrivilegesEvaluator evaluator;
private volatile ThreadPool threadPool;
private volatile IndexBaseConfigurationRepository cr;
private volatile AdminDNs adminDns;
private volatile ClusterService cs;
private volatile AuditLog auditLog;
private volatile BackendRegistry backendRegistry;
private volatile SslExceptionHandler sslExceptionHandler;
private volatile Client localClient;
private final boolean disabled;
private final boolean enterpriseModulesEnabled;
private final boolean sslOnly;
private final List demoCertHashes = new ArrayList(3);
private volatile SearchGuardFilter sgf;
private volatile ComplianceConfig complianceConfig;
private volatile IndexResolverReplacer irr;
private volatile NamedXContentRegistry namedXContentRegistry = null;
private volatile DlsFlsRequestValve dlsFlsValve = null;
@Override
public void close() throws IOException {
//TODO implement close
super.close();
}
private final SslExceptionHandler evaluateSslExceptionHandler() {
if (client || tribeNodeClient || disabled || sslOnly) {
return new SslExceptionHandler() {
};
}
return Objects.requireNonNull(sslExceptionHandler);
}
private static boolean isDisabled(final Settings settings) {
return settings.getAsBoolean(ConfigConstants.SEARCHGUARD_DISABLED, false);
}
private static boolean isSslOnlyMode(final Settings settings) {
return settings.getAsBoolean(ConfigConstants.SEARCHGUARD_SSL_ONLY, false);
}
public SearchGuardPlugin(final Settings settings, final Path configPath) {
super(settings, configPath, isDisabled(settings));
disabled = isDisabled(settings);
if (disabled) {
this.tribeNodeClient = false;
this.dlsFlsAvailable = false;
this.dlsFlsConstructor = null;
this.enterpriseModulesEnabled = false;
this.sslOnly = false;
complianceConfig = null;
log.warn("Search Guard plugin installed but disabled. This can expose your configuration (including passwords) to the public.");
return;
}
sslOnly = isSslOnlyMode(settings);
if (sslOnly) {
this.tribeNodeClient = false;
this.dlsFlsAvailable = false;
this.dlsFlsConstructor = null;
this.enterpriseModulesEnabled = false;
complianceConfig = null;
log.warn("Search Guard plugin run in ssl only mode. No authentication or authorization is performed");
return;
}
demoCertHashes.add("54a92508de7a39d06242a0ffbf59414d7eb478633c719e6af03938daf6de8a1a");
demoCertHashes.add("742e4659c79d7cad89ea86aab70aea490f23bbfc7e72abd5f0a5d3fb4c84d212");
demoCertHashes.add("db1264612891406639ecd25c894f256b7c5a6b7e1d9054cbe37b77acd2ddd913");
demoCertHashes.add("2a5398e20fcb851ec30aa141f37233ee91a802683415be2945c3c312c65c97cf");
demoCertHashes.add("33129547ce617f784c04e965104b2c671cce9e794d1c64c7efe58c77026246ae");
demoCertHashes.add("c4af0297cc75546e1905bdfe3934a950161eee11173d979ce929f086fdf9794d");
demoCertHashes.add("7a355f42c90e7543a267fbe3976c02f619036f5a34ce712995a22b342d83c3ce");
demoCertHashes.add("a9b5eca1399ec8518081c0d4a21a34eec4589087ce64c04fb01a488f9ad8edc9");
//new certs 04/2018
demoCertHashes.add("d14aefe70a592d7a29e14f3ff89c3d0070c99e87d21776aa07d333ee877e758f");
demoCertHashes.add("54a70016e0837a2b0c5658d1032d7ca32e432c62c55f01a2bf5adcb69a0a7ba9");
demoCertHashes.add("bdc141ab2272c779d0f242b79063152c49e1b06a2af05e0fd90d505f2b44d5f5");
demoCertHashes.add("3e839e2b059036a99ee4f742814995f2fb0ced7e9d68a47851f43a3c630b5324");
demoCertHashes.add("9b13661c073d864c28ad7b13eda67dcb6cbc2f04d116adc7c817c20b4c7ed361");
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
if (Security.getProvider("BC") == null) {
Security.addProvider(new BouncyCastleProvider());
}
return null;
}
});
enterpriseModulesEnabled = settings.getAsBoolean(ConfigConstants.SEARCHGUARD_ENTERPRISE_MODULES_ENABLED, true);
ReflectionHelper.init(enterpriseModulesEnabled);
ReflectionHelper.registerMngtRestApiHandler(settings);
log.info("Clustername: {}", settings.get("cluster.name", "elasticsearch"));
if (!transportSSLEnabled) {
throw new IllegalStateException(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_ENABLED + " must be set to 'true'");
}
if (log.isDebugEnabled() && this.settings.getByPrefix("tribe").size() > 0) {
log.debug("Tribe configuration detected: {}", this.settings);
}
boolean tribeNode = this.settings.get("tribe.name", null) == null && this.settings.getByPrefix("tribe").size() > 0;
tribeNodeClient = this.settings.get("tribe.name", null) != null;
log.debug("This node [{}] is a transportClient: {}/tribeNode: {}/tribeNodeClient: {}", settings.get("node.name"), client, tribeNode,
tribeNodeClient);
if (!client) {
dlsFlsConstructor = ReflectionHelper.instantiateDlsFlsConstructor();
dlsFlsAvailable = dlsFlsConstructor != null;
} else {
dlsFlsAvailable = false;
dlsFlsConstructor = null;
}
if (!client && !tribeNodeClient) {
final List filesWithWrongPermissions = AccessController.doPrivileged(new PrivilegedAction>() {
@Override
public List run() {
final Path confPath = new Environment(settings, configPath).configFile().toAbsolutePath();
if (Files.isDirectory(confPath, LinkOption.NOFOLLOW_LINKS)) {
try (Stream s = Files.walk(confPath)) {
return s.distinct().filter(p -> checkFilePermissions(p)).collect(Collectors.toList());
} catch (Exception e) {
log.error(e);
return null;
}
}
return Collections.emptyList();
}
});
if (filesWithWrongPermissions != null && filesWithWrongPermissions.size() > 0) {
for (final Path p : filesWithWrongPermissions) {
if (Files.isDirectory(p, LinkOption.NOFOLLOW_LINKS)) {
log.warn("Directory " + p + " has insecure file permissions (should be 0700)");
} else {
log.warn("File " + p + " has insecure file permissions (should be 0600)");
}
}
}
}
if (!client && !tribeNodeClient && !settings.getAsBoolean(ConfigConstants.SEARCHGUARD_ALLOW_UNSAFE_DEMOCERTIFICATES, false)) {
//check for demo certificates
final List files = AccessController.doPrivileged(new PrivilegedAction>() {
@Override
public List run() {
final Path confPath = new Environment(settings, configPath).configFile().toAbsolutePath();
if (Files.isDirectory(confPath, LinkOption.NOFOLLOW_LINKS)) {
try (Stream s = Files.walk(confPath)) {
return s.distinct().map(p -> sha256(p)).collect(Collectors.toList());
} catch (Exception e) {
log.error(e);
return null;
}
}
return Collections.emptyList();
}
});
if (files != null) {
demoCertHashes.retainAll(files);
if (!demoCertHashes.isEmpty()) {
log.error("Demo certificates found but " + ConfigConstants.SEARCHGUARD_ALLOW_UNSAFE_DEMOCERTIFICATES + " is set to false."
+ "See http://docs.search-guard.com/latest/demo-installer-generated-artefacts#allow-demo-certificates-and-auto-initialization");
throw new RuntimeException("Demo certificates found " + demoCertHashes);
}
} else {
throw new RuntimeException("Unable to look for demo certificates");
}
}
}
private String sha256(Path p) {
if (!Files.isRegularFile(p, LinkOption.NOFOLLOW_LINKS)) {
return "";
}
if (!Files.isReadable(p)) {
log.debug("Unreadable file " + p + " found");
return "";
}
try {
MessageDigest digester = MessageDigest.getInstance("SHA256");
final String hash = org.bouncycastle.util.encoders.Hex.toHexString(digester.digest(Files.readAllBytes(p)));
log.debug(hash + " :: " + p);
return hash;
} catch (Exception e) {
throw new ElasticsearchSecurityException("Unable to digest file " + p, e);
}
}
private boolean checkFilePermissions(final Path p) {
if (p == null) {
return false;
}
Set perms;
try {
perms = Files.getPosixFilePermissions(p, LinkOption.NOFOLLOW_LINKS);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Cannot determine posix file permissions for {} due to {}", p, e);
}
//ignore, can happen on windows
return false;
}
if (Files.isDirectory(p, LinkOption.NOFOLLOW_LINKS)) {
if (perms.contains(PosixFilePermission.OTHERS_EXECUTE)) {
// no x for others must be set
return true;
}
} else {
if (perms.contains(PosixFilePermission.OWNER_EXECUTE) || perms.contains(PosixFilePermission.GROUP_EXECUTE)
|| perms.contains(PosixFilePermission.OTHERS_EXECUTE)) {
// no x must be set
return true;
}
}
if (perms.contains(PosixFilePermission.OTHERS_READ) || perms.contains(PosixFilePermission.OTHERS_WRITE)) {
// no permissions for "others" allowed
return true;
}
//if (perms.contains(PosixFilePermission.GROUP_READ) || perms.contains(PosixFilePermission.GROUP_WRITE)) {
// // no permissions for "group" allowed
// return true;
//}
return false;
}
@Override
public List getRestHandlers(Settings settings, RestController restController, ClusterSettings clusterSettings,
IndexScopedSettings indexScopedSettings, SettingsFilter settingsFilter, IndexNameExpressionResolver indexNameExpressionResolver,
Supplier nodesInCluster) {
final List handlers = new ArrayList(1);
if (!client && !tribeNodeClient && !disabled) {
handlers.addAll(super.getRestHandlers(settings, restController, clusterSettings, indexScopedSettings, settingsFilter,
indexNameExpressionResolver, nodesInCluster));
if (!sslOnly) {
handlers.add(
new SearchGuardInfoAction(settings, restController, Objects.requireNonNull(evaluator), Objects.requireNonNull(threadPool)));
handlers.add(new KibanaInfoAction(settings, restController, Objects.requireNonNull(evaluator), Objects.requireNonNull(threadPool)));
handlers.add(new SearchGuardLicenseAction(settings, restController));
handlers.add(new SearchGuardHealthAction(settings, restController, Objects.requireNonNull(backendRegistry)));
handlers.add(new TenantInfoAction(settings, restController, Objects.requireNonNull(evaluator), Objects.requireNonNull(threadPool),
Objects.requireNonNull(cs), Objects.requireNonNull(adminDns)));
Collection apiHandler = ReflectionHelper.instantiateMngtRestApiHandler(settings, configPath, restController, localClient,
adminDns, cr, cs, Objects.requireNonNull(principalExtractor), evaluator, threadPool, Objects.requireNonNull(auditLog));
handlers.addAll(apiHandler);
log.debug("Added {} management rest handler(s)", apiHandler.size());
}
}
return handlers;
}
@Override
public UnaryOperator getRestHandlerWrapper(final ThreadContext threadContext) {
if (client || disabled || sslOnly) {
return (rh) -> rh;
}
return (rh) -> sgRestHandler.wrap(rh);
}
@Override
public List> getActions() {
List> actions = new ArrayList<>(1);
if (!tribeNodeClient && !disabled && !sslOnly) {
actions.add(new ActionHandler<>(ConfigUpdateAction.INSTANCE, TransportConfigUpdateAction.class));
actions.add(new ActionHandler<>(LicenseInfoAction.INSTANCE, TransportLicenseInfoAction.class));
actions.add(new ActionHandler<>(WhoAmIAction.INSTANCE, TransportWhoAmIAction.class));
}
return actions;
}
private IndexSearcherWrapper loadFlsDlsIndexSearcherWrapper(final IndexService indexService, final ComplianceIndexingOperationListener ciol,
final ComplianceConfig complianceConfig) {
try {
namedXContentRegistry = indexService.xContentRegistry();
IndexSearcherWrapper flsdlsWrapper = (IndexSearcherWrapper) dlsFlsConstructor.newInstance(indexService, settings,
Objects.requireNonNull(adminDns), Objects.requireNonNull(cs), Objects.requireNonNull(auditLog), Objects.requireNonNull(ciol),
Objects.requireNonNull(complianceConfig));
if (log.isDebugEnabled()) {
log.debug("FLS/DLS enabled for index {}", indexService.index().getName());
}
return flsdlsWrapper;
} catch (Exception ex) {
throw new RuntimeException("Failed to enable FLS/DLS", ex);
}
}
@Override
public void onIndexModule(IndexModule indexModule) {
//called for every index!
if (!disabled && !client && !sslOnly) {
log.debug("Handle complianceConfig=" + complianceConfig + "/dlsFlsAvailable: " + dlsFlsAvailable + "/auditLog=" + auditLog.getClass()
+ " for onIndexModule() of index " + indexModule.getIndex().getName());
if (dlsFlsAvailable) {
final ComplianceIndexingOperationListener ciol;
assert complianceConfig != null : "compliance config must not be null here";
if (complianceConfig.writeHistoryEnabledForIndex(indexModule.getIndex().getName())) {
ciol = ReflectionHelper.instantiateComplianceListener(complianceConfig, Objects.requireNonNull(auditLog));
indexModule.addIndexOperationListener(ciol);
} else {
ciol = new ComplianceIndexingOperationListener();
}
indexModule.setSearcherWrapper(indexService -> loadFlsDlsIndexSearcherWrapper(indexService, ciol, complianceConfig));
indexModule.forceQueryCacheProvider((indexSettings, nodeCache) -> new QueryCache() {
@Override
public Index index() {
return indexSettings.getIndex();
}
@Override
public void close() throws ElasticsearchException {
clear("close");
}
@Override
public void clear(String reason) {
nodeCache.clearIndex(index().getName());
}
@Override
public Weight doCache(Weight weight, QueryCachingPolicy policy) {
final Map> allowedFlsFields = (Map>) HeaderHelper
.deserializeSafeFromHeader(threadPool.getThreadContext(), ConfigConstants.SG_FLS_FIELDS_HEADER);
if (SgUtils.evalMap(allowedFlsFields, index().getName()) != null) {
return weight;
} else {
final Map> maskedFieldsMap = (Map>) HeaderHelper
.deserializeSafeFromHeader(threadPool.getThreadContext(), ConfigConstants.SG_MASKED_FIELD_HEADER);
if (SgUtils.evalMap(maskedFieldsMap, index().getName()) != null) {
return weight;
} else {
return nodeCache.doCache(weight, policy);
}
}
}
});
} else {
assert complianceConfig == null : "compliance config must be null here";
indexModule.setSearcherWrapper(
indexService -> new SearchGuardIndexSearcherWrapper(indexService, settings, Objects.requireNonNull(adminDns)));
}
indexModule.addSearchOperationListener(new SearchOperationListener() {
@Override
public void onNewContext(SearchContext context) {
if(enterpriseModulesEnabled) {
dlsFlsValve.handleSearchContext(context, threadPool, namedXContentRegistry);
}
}
@Override
public void onNewScrollContext(SearchContext context) {
final ScrollContext scrollContext = context.scrollContext();
if (scrollContext != null) {
final boolean interClusterRequest = HeaderHelper.isInterClusterRequest(threadPool.getThreadContext());
if (Origin.LOCAL.toString().equals(threadPool.getThreadContext().getTransient(ConfigConstants.SG_ORIGIN))
&& (interClusterRequest || HeaderHelper.isDirectRequest(threadPool.getThreadContext()))
) {
scrollContext.putInContext("_sg_scroll_auth_local", Boolean.TRUE);
} else {
scrollContext.putInContext("_sg_scroll_auth", threadPool.getThreadContext().getTransient(ConfigConstants.SG_USER));
}
}
}
@Override
public void validateSearchContext(SearchContext context, TransportRequest transportRequest) {
final ScrollContext scrollContext = context.scrollContext();
if (scrollContext != null) {
final Object _isLocal = scrollContext.getFromContext("_sg_scroll_auth_local");
final Object _user = scrollContext.getFromContext("_sg_scroll_auth");
if (_user != null && (_user instanceof User)) {
final User scrollUser = (User) _user;
final User currentUser = threadPool.getThreadContext().getTransient(ConfigConstants.SG_USER);
if (!scrollUser.equals(currentUser)) {
auditLog.logMissingPrivileges(SearchScrollAction.NAME, transportRequest, context.getTask());
log.error("Wrong user {} in scroll context, expected {}", scrollUser, currentUser);
throw new ElasticsearchSecurityException("Wrong user in scroll context", RestStatus.FORBIDDEN);
}
} else if (_isLocal != Boolean.TRUE) {
auditLog.logMissingPrivileges(SearchScrollAction.NAME, transportRequest, context.getTask());
throw new ElasticsearchSecurityException("No user in scroll context", RestStatus.FORBIDDEN);
}
}
}
});
}
}
@Override
public List getActionFilters() {
List filters = new ArrayList<>(1);
if (!tribeNodeClient && !client && !disabled && !sslOnly) {
filters.add(Objects.requireNonNull(sgf));
}
return filters;
}
@Override
public List getTransportInterceptors(NamedWriteableRegistry namedWriteableRegistry, ThreadContext threadContext) {
List interceptors = new ArrayList(1);
if (!client && !tribeNodeClient && !disabled && !sslOnly) {
interceptors.add(new TransportInterceptor() {
@Override
public TransportRequestHandler interceptHandler(String action, String executor,
boolean forceExecution, TransportRequestHandler actualHandler) {
return new TransportRequestHandler() {
@Override
public void messageReceived(T request, TransportChannel channel, Task task) throws Exception {
sgi.getHandler(action, actualHandler).messageReceived(request, channel, task);
}
@Override
public void messageReceived(T request, TransportChannel channel) throws Exception {
sgi.getHandler(action, actualHandler).messageReceived(request, channel);
}
};
}
@Override
public AsyncSender interceptSender(AsyncSender sender) {
return new AsyncSender() {
@Override
public void sendRequest(Connection connection, String action, TransportRequest request,
TransportRequestOptions options, TransportResponseHandler handler) {
sgi.sendRequestDecorate(sender, connection, action, request, options, handler);
}
};
}
});
}
return interceptors;
}
@Override
public Map> getTransports(Settings settings, ThreadPool threadPool,
PageCacheRecycler pageCacheRecycler, CircuitBreakerService circuitBreakerService,
NamedWriteableRegistry namedWriteableRegistry, NetworkService networkService) {
Map> transports = new HashMap>();
if(sslOnly) {
return super.getTransports(settings, threadPool, pageCacheRecycler, circuitBreakerService, namedWriteableRegistry, networkService);
}
if (transportSSLEnabled) {
transports.put("com.floragunn.searchguard.ssl.http.netty.SearchGuardSSLNettyTransport",
() -> new SearchGuardSSLNettyTransport(settings, Version.CURRENT, threadPool, networkService, pageCacheRecycler, namedWriteableRegistry,
circuitBreakerService, sgks, evaluateSslExceptionHandler()));
}
return transports;
}
@Override
public Map> getHttpTransports(Settings settings, ThreadPool threadPool, BigArrays bigArrays,
CircuitBreakerService circuitBreakerService, NamedWriteableRegistry namedWriteableRegistry, NamedXContentRegistry xContentRegistry,
NetworkService networkService, Dispatcher dispatcher) {
if (sslOnly) {
return super.getHttpTransports(settings, threadPool, bigArrays, circuitBreakerService, namedWriteableRegistry, xContentRegistry,
networkService, dispatcher);
}
Map> httpTransports = new HashMap>(1);
if (!disabled) {
if (!client && httpSSLEnabled && !tribeNodeClient) {
final ValidatingDispatcher validatingDispatcher = new ValidatingDispatcher(threadPool.getThreadContext(), dispatcher, settings,
configPath, evaluateSslExceptionHandler());
//TODO close sghst
final SearchGuardHttpServerTransport sghst = new SearchGuardHttpServerTransport(settings, networkService, bigArrays, threadPool, sgks,
evaluateSslExceptionHandler(), xContentRegistry, validatingDispatcher);
httpTransports.put("com.floragunn.searchguard.http.SearchGuardHttpServerTransport", () -> sghst);
} else if (!client && !tribeNodeClient) {
httpTransports.put("com.floragunn.searchguard.http.SearchGuardHttpServerTransport",
() -> new SearchGuardNonSslHttpServerTransport(settings, networkService, bigArrays, threadPool, xContentRegistry,
dispatcher));
}
}
return httpTransports;
}
@Override
public Collection createComponents(Client localClient, ClusterService clusterService, ThreadPool threadPool,
ResourceWatcherService resourceWatcherService, ScriptService scriptService, NamedXContentRegistry xContentRegistry,
Environment environment, NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry) {
if (sslOnly) {
return super.createComponents(localClient, clusterService, threadPool, resourceWatcherService, scriptService, xContentRegistry,
environment, nodeEnvironment, namedWriteableRegistry);
}
this.threadPool = threadPool;
this.cs = clusterService;
this.localClient = localClient;
final List components = new ArrayList();
if (client || tribeNodeClient || disabled) {
return components;
}
final ClusterInfoHolder cih = new ClusterInfoHolder();
this.cs.addListener(cih);
dlsFlsValve = ReflectionHelper.instantiateDlsFlsValve();
final IndexNameExpressionResolver resolver = new IndexNameExpressionResolver(settings);
irr = new IndexResolverReplacer(resolver, clusterService, cih);
auditLog = ReflectionHelper.instantiateAuditLog(settings, configPath, localClient, threadPool, resolver, clusterService);
complianceConfig = (dlsFlsAvailable && (auditLog.getClass() != NullAuditLog.class))
? new ComplianceConfig(environment, Objects.requireNonNull(irr), auditLog)
: null;
log.debug("Compliance config is " + complianceConfig + " because of dlsFlsAvailable: " + dlsFlsAvailable + " and auditLog="
+ auditLog.getClass());
auditLog.setComplianceConfig(complianceConfig);
sslExceptionHandler = new AuditLogSslExceptionHandler(auditLog);
final String DEFAULT_INTERCLUSTER_REQUEST_EVALUATOR_CLASS = DefaultInterClusterRequestEvaluator.class.getName();
InterClusterRequestEvaluator interClusterRequestEvaluator = new DefaultInterClusterRequestEvaluator(settings);
final String className = settings.get(ConfigConstants.SG_INTERCLUSTER_REQUEST_EVALUATOR_CLASS, DEFAULT_INTERCLUSTER_REQUEST_EVALUATOR_CLASS);
log.debug("Using {} as intercluster request evaluator class", className);
if (!DEFAULT_INTERCLUSTER_REQUEST_EVALUATOR_CLASS.equals(className)) {
interClusterRequestEvaluator = ReflectionHelper.instantiateInterClusterRequestEvaluator(className, settings);
}
final PrivilegesInterceptor privilegesInterceptor = ReflectionHelper.instantiatePrivilegesInterceptorImpl(resolver, clusterService,
localClient, threadPool);
adminDns = new AdminDNs(settings);
//final PrincipalExtractor pe = new DefaultPrincipalExtractor();
cr = (IndexBaseConfigurationRepository) IndexBaseConfigurationRepository.create(settings, this.configPath, threadPool, localClient,
clusterService, auditLog, complianceConfig);
cr.subscribeOnLicenseChange(complianceConfig);
cr.subscribeOnChange(ConfigConstants.CONFIGNAME_CONFIG, irr);
final InternalAuthenticationBackend iab = new InternalAuthenticationBackend(cr);
final XFFResolver xffResolver = new XFFResolver(threadPool);
cr.subscribeOnChange(ConfigConstants.CONFIGNAME_CONFIG, xffResolver);
backendRegistry = new BackendRegistry(settings, configPath, adminDns, xffResolver, iab, auditLog, threadPool);
cr.subscribeOnChange(ConfigConstants.CONFIGNAME_CONFIG, backendRegistry);
final ActionGroupHolder ah = new ActionGroupHolder(cr);
evaluator = new PrivilegesEvaluator(clusterService, threadPool, cr, ah, resolver, auditLog, settings, privilegesInterceptor, cih, irr,
enterpriseModulesEnabled);
final CompatConfig compatConfig = new CompatConfig(environment);
cr.subscribeOnChange(ConfigConstants.CONFIGNAME_CONFIG, compatConfig);
sgf = new SearchGuardFilter(evaluator, adminDns, dlsFlsValve, auditLog, threadPool, cs, complianceConfig, compatConfig);
final String principalExtractorClass = settings.get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_PRINCIPAL_EXTRACTOR_CLASS, null);
if (principalExtractorClass == null) {
principalExtractor = new com.floragunn.searchguard.ssl.transport.DefaultPrincipalExtractor();
} else {
principalExtractor = ReflectionHelper.instantiatePrincipalExtractor(principalExtractorClass);
}
sgi = new SearchGuardInterceptor(settings, threadPool, backendRegistry, auditLog, principalExtractor, interClusterRequestEvaluator, cs,
Objects.requireNonNull(sslExceptionHandler), Objects.requireNonNull(cih));
components.add(principalExtractor);
cr.subscribeOnChange(ConfigConstants.CONFIGNAME_CONFIG, new ConfigurationChangeListener() {
@Override
public void onChange(Settings unused) {
//auditLog.logExternalConfig(settings, environment);
}
});
components.add(adminDns);
//components.add(auditLog);
components.add(cr);
components.add(iab);
components.add(xffResolver);
components.add(backendRegistry);
components.add(ah);
components.add(evaluator);
components.add(sgi);
sgRestHandler = new SearchGuardRestFilter(backendRegistry, auditLog, threadPool, principalExtractor, settings, configPath, compatConfig);
return components;
}
@Override
public Settings additionalSettings() {
if (disabled) {
return Settings.EMPTY;
}
final Settings.Builder builder = Settings.builder();
builder.put(super.additionalSettings());
if (!sslOnly) {
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, "com.floragunn.searchguard.ssl.http.netty.SearchGuardSSLNettyTransport");
builder.put(NetworkModule.HTTP_TYPE_KEY, "com.floragunn.searchguard.http.SearchGuardHttpServerTransport");
}
return builder.build();
}
@Override
public List> getSettings() {
List> settings = new ArrayList>();
settings.addAll(super.getSettings());
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_SSL_ONLY, false, Property.NodeScope, Property.Filtered));
if (!sslOnly) {
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_AUTHCZ_ADMIN_DN, Collections.emptyList(), Function.identity(),
Property.NodeScope)); //not filtered here
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_CONFIG_INDEX_NAME, Property.NodeScope, Property.Filtered));
settings.add(Setting.groupSetting(ConfigConstants.SEARCHGUARD_AUTHCZ_IMPERSONATION_DN + ".", Property.NodeScope)); //not filtered here
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_CERT_OID, Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_CERT_INTERCLUSTER_REQUEST_EVALUATOR_CLASS, Property.NodeScope,
Property.Filtered));
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_NODES_DN, Collections.emptyList(), Function.identity(), Property.NodeScope));//not filtered here
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_ENABLE_SNAPSHOT_RESTORE_PRIVILEGE,
ConfigConstants.SG_DEFAULT_ENABLE_SNAPSHOT_RESTORE_PRIVILEGE, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_CHECK_SNAPSHOT_RESTORE_WRITE_PRIVILEGES,
ConfigConstants.SG_DEFAULT_CHECK_SNAPSHOT_RESTORE_WRITE_PRIVILEGES, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_DISABLED, false, Property.NodeScope, Property.Filtered));
settings.add(Setting.intSetting(ConfigConstants.SEARCHGUARD_CACHE_TTL_MINUTES, 60, 0, Property.NodeScope, Property.Filtered));
//SG6
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_ENTERPRISE_MODULES_ENABLED, true, Property.NodeScope, Property.Filtered));
settings.add(
Setting.boolSetting(ConfigConstants.SEARCHGUARD_ALLOW_UNSAFE_DEMOCERTIFICATES, false, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_ALLOW_DEFAULT_INIT_SGINDEX, false, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_BACKGROUND_INIT_IF_SGINDEX_NOT_EXIST, true, Property.NodeScope, Property.Filtered));
settings.add(Setting.groupSetting(ConfigConstants.SEARCHGUARD_AUTHCZ_REST_IMPERSONATION_USERS + ".", Property.NodeScope)); //not filtered here
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_ROLES_MAPPING_RESOLUTION, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_DISABLE_ENVVAR_REPLACEMENT, false, Property.NodeScope, Property.Filtered));
//settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_DISABLE_TYPE_SECURITY, false, Property.NodeScope, Property.Filtered));
//TODO remove searchguard.tribe.clustername?
//settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_TRIBE_CLUSTERNAME, Property.NodeScope, Property.Filtered));
// SG6 - Audit
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_AUDIT_TYPE_DEFAULT, Property.NodeScope, Property.Filtered));
settings.add(Setting.groupSetting(ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_ROUTES + ".", Property.NodeScope));
settings.add(Setting.groupSetting(ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_ENDPOINTS + ".", Property.NodeScope));
settings.add(Setting.intSetting(ConfigConstants.SEARCHGUARD_AUDIT_THREADPOOL_SIZE, 10, Property.NodeScope, Property.Filtered));
settings.add(Setting.intSetting(ConfigConstants.SEARCHGUARD_AUDIT_THREADPOOL_MAX_QUEUE_LEN, 100 * 1000, Property.NodeScope,
Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_AUDIT_LOG_REQUEST_BODY, true, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_AUDIT_RESOLVE_INDICES, true, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_AUDIT_ENABLE_REST, true, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_AUDIT_ENABLE_TRANSPORT, true, Property.NodeScope, Property.Filtered));
final List disabledCategories = new ArrayList(2);
disabledCategories.add("AUTHENTICATED");
disabledCategories.add("GRANTED_PRIVILEGES");
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, disabledCategories,
Function.identity(), Property.NodeScope)); //not filtered here
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, disabledCategories,
Function.identity(), Property.NodeScope)); //not filtered here
final List ignoredUsers = new ArrayList(2);
ignoredUsers.add("kibanaserver");
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_AUDIT_IGNORE_USERS, ignoredUsers, Function.identity(), Property.NodeScope)); //not filtered here
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_AUDIT_IGNORE_REQUESTS, Collections.emptyList(), Function.identity(),
Property.NodeScope)); //not filtered here
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_AUDIT_RESOLVE_BULK_REQUESTS, false, Property.NodeScope, Property.Filtered));
settings.add(
Setting.boolSetting(ConfigConstants.SEARCHGUARD_AUDIT_EXCLUDE_SENSITIVE_HEADERS, true, Property.NodeScope, Property.Filtered));
// SG6 - Audit - Sink
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_ES_INDEX,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_ES_TYPE,
Property.NodeScope, Property.Filtered));
// External ES
settings.add(Setting.listSetting(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_HTTP_ENDPOINTS,
Lists.newArrayList("localhost:9200"), Function.identity(), Property.NodeScope)); //not filtered here
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_USERNAME,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_PASSWORD,
Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_ENABLE_SSL, false,
Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_VERIFY_HOSTNAMES, true,
Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_ENABLE_SSL_CLIENT_AUTH,
false, Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_PEMCERT_CONTENT,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_PEMCERT_FILEPATH,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_PEMKEY_CONTENT,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_PEMKEY_FILEPATH,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_PEMKEY_PASSWORD,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_PEMTRUSTEDCAS_CONTENT,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_PEMTRUSTEDCAS_FILEPATH,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_JKS_CERT_ALIAS,
Property.NodeScope, Property.Filtered));
settings.add(Setting.listSetting(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_ENABLED_SSL_CIPHERS,
Collections.emptyList(), Function.identity(), Property.NodeScope));//not filtered here
settings.add(Setting.listSetting(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_EXTERNAL_ES_ENABLED_SSL_PROTOCOLS,
Collections.emptyList(), Function.identity(), Property.NodeScope));//not filtered here
// Webhooks
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_WEBHOOK_URL,
Property.NodeScope, Property.Filtered));
settings.add(
Setting.simpleString(ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_WEBHOOK_FORMAT,
Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_WEBHOOK_SSL_VERIFY, true,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_WEBHOOK_PEMTRUSTEDCAS_FILEPATH,
Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_WEBHOOK_PEMTRUSTEDCAS_CONTENT,
Property.NodeScope, Property.Filtered));
// Log4j
settings.add(Setting.simpleString(
ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_LOG4J_LOGGER_NAME, Property.NodeScope,
Property.Filtered));
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SEARCHGUARD_AUDIT_LOG4J_LEVEL,
Property.NodeScope, Property.Filtered));
// Kerberos
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_KERBEROS_KRB5_FILEPATH, Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_KERBEROS_ACCEPTOR_KEYTAB_FILEPATH, Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_KERBEROS_ACCEPTOR_PRINCIPAL, Property.NodeScope, Property.Filtered));
// SG6 - REST API
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_RESTAPI_ROLES_ENABLED, Collections.emptyList(), Function.identity(),
Property.NodeScope)); //not filtered here
settings.add(Setting.groupSetting(ConfigConstants.SEARCHGUARD_RESTAPI_ENDPOINTS_DISABLED + ".", Property.NodeScope));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_UNSUPPORTED_RESTAPI_ACCEPT_INVALID_LICENSE, false, Property.NodeScope,
Property.Filtered));
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_RESTAPI_PASSWORD_VALIDATION_REGEX, Property.NodeScope, Property.Filtered));
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_RESTAPI_PASSWORD_VALIDATION_ERROR_MESSAGE, Property.NodeScope,
Property.Filtered));
// Compliance
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_HISTORY_WRITE_WATCHED_INDICES, Collections.emptyList(),
Function.identity(), Property.NodeScope)); //not filtered here
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_HISTORY_READ_WATCHED_FIELDS, Collections.emptyList(),
Function.identity(), Property.NodeScope)); //not filtered here
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_HISTORY_WRITE_METADATA_ONLY, false, Property.NodeScope,
Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_HISTORY_READ_METADATA_ONLY, false, Property.NodeScope,
Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, false, Property.NodeScope,
Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false, Property.NodeScope,
Property.Filtered));
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_HISTORY_READ_IGNORE_USERS, Collections.emptyList(),
Function.identity(), Property.NodeScope)); //not filtered here
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_HISTORY_WRITE_IGNORE_USERS, Collections.emptyList(),
Function.identity(), Property.NodeScope)); //not filtered here
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_DISABLE_ANONYMOUS_AUTHENTICATION, false, Property.NodeScope,
Property.Filtered));
settings.add(Setting.listSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_IMMUTABLE_INDICES, Collections.emptyList(), Function.identity(),
Property.NodeScope)); //not filtered here
settings.add(Setting.simpleString(ConfigConstants.SEARCHGUARD_COMPLIANCE_SALT, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, false, Property.NodeScope,
Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_FILTER_SGINDEX_FROM_ALL_REQUESTS, false, Property.NodeScope,
Property.Filtered));
//compat
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_UNSUPPORTED_DISABLE_INTERTRANSPORT_AUTH_INITIALLY, false, Property.NodeScope,
Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_UNSUPPORTED_DISABLE_REST_AUTH_INITIALLY, false, Property.NodeScope,
Property.Filtered));
// system integration
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_UNSUPPORTED_RESTORE_SGINDEX_ENABLED, false, Property.NodeScope,
Property.Filtered));
settings.add(
Setting.boolSetting(ConfigConstants.SEARCHGUARD_UNSUPPORTED_INJECT_USER_ENABLED, false, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_UNSUPPORTED_INJECT_ADMIN_USER_ENABLED, false, Property.NodeScope,
Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_UNSUPPORTED_ALLOW_NOW_IN_DLS, false, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.SEARCHGUARD_UNSUPPORTED_RESTAPI_ALLOW_SGCONFIG_MODIFICATION, false, Property.NodeScope, Property.Filtered));
}
return settings;
}
@Override
public List getSettingsFilter() {
List settingsFilter = new ArrayList<>();
if (disabled) {
return settingsFilter;
}
settingsFilter.add("searchguard.*");
return settingsFilter;
}
@Override
public void onNodeStarted() {
final Set sgModules = ReflectionHelper.getModulesLoaded();
log.info("{} Search Guard modules loaded so far: {}", sgModules.size(), sgModules);
}
//below is a hack because it seems not possible to access RepositoriesService from a non guice class
//the way of how deguice is organized is really a mess - hope this can be fixed in later versions
//TODO check if this could be removed
@Override
public Collection> getGuiceServiceClasses() {
if (client || tribeNodeClient || disabled || sslOnly) {
return Collections.emptyList();
}
final List> services = new ArrayList<>(1);
services.add(GuiceHolder.class);
return services;
}
@Override
public Function> getFieldFilter() {
return index -> {
if (threadPool == null) {
return field -> true;
}
final Map> allowedFlsFields = (Map>) HeaderHelper
.deserializeSafeFromHeader(threadPool.getThreadContext(), ConfigConstants.SG_FLS_FIELDS_HEADER);
final String eval = SgUtils.evalMap(allowedFlsFields, index);
if (eval == null) {
return field -> true;
} else {
final Set includesExcludes = allowedFlsFields.get(eval);
final Set includesSet = new HashSet<>(includesExcludes.size());
final Set excludesSet = new HashSet<>(includesExcludes.size());
for (final String incExc : includesExcludes) {
final char firstChar = incExc.charAt(0);
if (firstChar == '!' || firstChar == '~') {
excludesSet.add(incExc.substring(1));
} else {
includesSet.add(incExc);
}
}
if (!excludesSet.isEmpty()) {
return field -> !WildcardMatcher.matchAny(excludesSet, handleKeyword(field));
} else {
return field -> WildcardMatcher.matchAny(includesSet, handleKeyword(field));
}
}
};
}
private static String handleKeyword(final String field) {
if (field != null && field.endsWith(KEYWORD)) {
return field.substring(0, field.length() - KEYWORD.length());
}
return field;
}
public static class GuiceHolder implements LifecycleComponent {
private static RepositoriesService repositoriesService;
private static RemoteClusterService remoteClusterService;
@Inject
public GuiceHolder(final RepositoriesService repositoriesService, final TransportService remoteClusterService) {
GuiceHolder.repositoriesService = repositoriesService;
GuiceHolder.remoteClusterService = remoteClusterService.getRemoteClusterService();
}
public static RepositoriesService getRepositoriesService() {
return repositoriesService;
}
public static RemoteClusterService getRemoteClusterService() {
return remoteClusterService;
}
@Override
public void close() {
}
@Override
public State lifecycleState() {
return null;
}
@Override
public void addLifecycleListener(LifecycleListener listener) {
}
@Override
public void removeLifecycleListener(LifecycleListener listener) {
}
@Override
public void start() {
}
@Override
public void stop() {
}
}
}