Skip to content

Commit

Permalink
Backport issue(#1156) and issue(#1057) to branch opendistro-1.6 (#1267)
Browse files Browse the repository at this point in the history
* Correcting setupSslOnlyMode to use AbstractSecurityUnitTest.hasCustomTransportSettings() (#1057)
(cherry picked from commit 70a4f70)

* Introducing passive_intertransport_auth to facilitate communication between nodes with adv sec enabled and nodes without adv sec enabled.(#1156)
(Cherry picked from commit 9adcd20)

Co-authored-by: Debjani Banerjee <56744681+debjanibnrj@users.noreply.github.com>
Co-authored-by: dhiAmzn <81139246+dhiAmzn@users.noreply.github.com>
  • Loading branch information
3 people committed Jul 15, 2021
1 parent fa034d1 commit 7a08fae
Show file tree
Hide file tree
Showing 28 changed files with 2,796 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@
import org.apache.lucene.index.DirectoryReader;
import com.amazon.opendistroforelasticsearch.security.ssl.rest.OpenDistroSecuritySSLReloadCertsAction;
import com.amazon.opendistroforelasticsearch.security.ssl.rest.OpenDistroSecuritySSLCertsInfoAction;
import com.amazon.opendistroforelasticsearch.security.filter.OpenDistroSecurityRestFilter;
import com.amazon.opendistroforelasticsearch.security.http.OpenDistroSecurityHttpServerTransport;
import com.amazon.opendistroforelasticsearch.security.ssl.OpenDistroSecuritySSLPlugin;
import com.amazon.opendistroforelasticsearch.security.transport.OpenDistroSecurityInterceptor;
import com.amazon.opendistroforelasticsearch.security.setting.OpenDistroDynamicSetting;
import com.amazon.opendistroforelasticsearch.security.setting.TransportPassiveAuthSetting;
import com.amazon.opendistroforelasticsearch.security.ssl.transport.DefaultPrincipalExtractor;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.amazon.opendistroforelasticsearch.security.ssl.transport.OpenDistroSSLConfig;
import org.apache.lucene.search.QueryCachingPolicy;
import org.apache.lucene.search.Weight;
Expand Down Expand Up @@ -193,6 +203,7 @@ public final class OpenDistroSecurityPlugin extends OpenDistroSecuritySSLPlugin
private AtomicBoolean externalConfigLogged = new AtomicBoolean();
private volatile NamedXContentRegistry namedXContentRegistry = null;
private volatile DlsFlsRequestValve dlsFlsValve = null;
private volatile OpenDistroDynamicSetting<Boolean> transportPassiveAuthSetting;

@Override
public void close() throws IOException {
Expand Down Expand Up @@ -227,6 +238,8 @@ public OpenDistroSecurityPlugin(final Settings settings, final Path configPath)
disabled = isDisabled(settings);
sslCertReloadEnabled = isSslCertReloadEnabled(settings);

transportPassiveAuthSetting = new TransportPassiveAuthSetting(settings);

if (disabled) {
this.dlsFlsAvailable = false;
this.dlsFlsConstructor = null;
Expand Down Expand Up @@ -738,6 +751,10 @@ public Collection<Object> createComponents(Client localClient, ClusterService cl
if (client || disabled) {
return components;
}

//Register opensearch dynamic settings
transportPassiveAuthSetting.registerClusterSettingsChangeListener(clusterService.getClusterSettings());

final ClusterInfoHolder cih = new ClusterInfoHolder();
this.cs.addListener(cih);

Expand Down Expand Up @@ -768,10 +785,8 @@ public Collection<Object> createComponents(Client localClient, ClusterService cl

final XFFResolver xffResolver = new XFFResolver(threadPool);
backendRegistry = new BackendRegistry(settings, adminDns, xffResolver, auditLog, threadPool);

final CompatConfig compatConfig = new CompatConfig(environment);


final CompatConfig compatConfig = new CompatConfig(environment, transportPassiveAuthSetting);

evaluator = new PrivilegesEvaluator(clusterService, threadPool, cr, resolver, auditLog,
settings, privilegesInterceptor, cih, irr, advancedModulesEnabled);
Expand All @@ -797,8 +812,9 @@ public Collection<Object> createComponents(Client localClient, ClusterService cl
principalExtractor = ReflectionHelper.instantiatePrincipalExtractor(principalExtractorClass);
}


odsi = new OpenDistroSecurityInterceptor(settings, threadPool, backendRegistry, auditLog, principalExtractor,
interClusterRequestEvaluator, cs, Objects.requireNonNull(sslExceptionHandler), Objects.requireNonNull(cih));
interClusterRequestEvaluator, cs, Objects.requireNonNull(sslExceptionHandler), Objects.requireNonNull(cih), openDistroSSLConfig);
components.add(principalExtractor);

// NOTE: We need to create DefaultInterClusterRequestEvaluator before creating ConfigurationRepository since the latter requires security index to be accessible which means
Expand Down Expand Up @@ -971,7 +987,7 @@ public List<Setting<?>> getSettings() {
settings.add(Setting.listSetting(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_IMMUTABLE_INDICES, Collections.emptyList(), Function.identity(), Property.NodeScope)); //not filtered here
settings.add(Setting.simpleString(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_SALT, Property.NodeScope, Property.Filtered));
settings.add(Setting.boolSetting(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, false, Property.NodeScope, Property.Filtered));

settings.add(transportPassiveAuthSetting.getDynamicSetting());
settings.add(Setting.boolSetting(ConfigConstants.OPENDISTRO_SECURITY_FILTER_SECURITYINDEX_FROM_ALL_REQUESTS, false, Property.NodeScope,
Property.Filtered));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

package com.amazon.opendistroforelasticsearch.security.configuration;

import com.amazon.opendistroforelasticsearch.security.setting.OpenDistroDynamicSetting;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.common.settings.Settings;
Expand All @@ -39,15 +40,18 @@
import com.amazon.opendistroforelasticsearch.security.securityconf.DynamicConfigModel;
import com.amazon.opendistroforelasticsearch.security.support.ConfigConstants;


public class CompatConfig {

private final Logger log = LogManager.getLogger(getClass());
private final Settings staticSettings;
private DynamicConfigModel dcm;
private final OpenDistroDynamicSetting<Boolean> transportPassiveAuthSetting;

public CompatConfig(final Environment environment) {
public CompatConfig(final Environment environment, final OpenDistroDynamicSetting<Boolean> transportPassiveAuthSetting) {
super();
this.staticSettings = environment.settings();
this.staticSettings = environment.settings();
this.transportPassiveAuthSetting = transportPassiveAuthSetting;
}

@Subscribe
Expand Down Expand Up @@ -100,4 +104,15 @@ public boolean transportInterClusterAuthEnabled() {
return true;
}
}

/**
* Returns true if passive transport auth is enabled
*/
public boolean transportInterClusterPassiveAuthEnabled() {
final boolean interClusterAuthInitiallyPassive = transportPassiveAuthSetting.getDynamicSettingValue();
if(log.isTraceEnabled()) {
log.trace("{} {}", ConfigConstants.OPENDISTRO_SECURITY_UNSUPPORTED_PASSIVE_INTERTRANSPORT_AUTH_INITIALLY, interClusterAuthInitiallyPassive);
}
return interClusterAuthInitiallyPassive;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ private <Request extends ActionRequest, Response extends ActionResponse> void ap
attachSourceFieldContext(request);
}

final User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);
User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);
final boolean userIsAdmin = isUserAdmin(user, adminDns);
final boolean interClusterRequest = HeaderHelper.isInterClusterRequest(threadContext);
final boolean trustedClusterRequest = HeaderHelper.isTrustedClusterRequest(threadContext);
Expand Down Expand Up @@ -245,14 +245,20 @@ private <Request extends ActionRequest, Response extends ActionResponse> void ap
return;
}

boolean skipSecurityIfDualMode = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_DUAL_MODE_SKIP_SECURITY) == Boolean.TRUE;
if((interClusterRequest || trustedClusterRequest || request.remoteAddress() == null) && !compatConfig.transportInterClusterAuthEnabled()) {
chain.proceed(task, action, request, listener);
return;
} else if((interClusterRequest || trustedClusterRequest || request.remoteAddress() == null || skipSecurityIfDualMode) && compatConfig.transportInterClusterPassiveAuthEnabled()) {
log.info("Transport auth in passive mode and no user found. Injecting default user");
user = User.DEFAULT_TRANSPORT_USER;
threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, user);
} else {
log.error("No user found for "+ action+" from "+request.remoteAddress()+" "+threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_ORIGIN)+" via "+threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_CHANNEL_TYPE)+" "+threadContext.getHeaders());
listener.onFailure(new ElasticsearchSecurityException("No user found for "+action, RestStatus.INTERNAL_SERVER_ERROR));
return;
}

log.error("No user found for "+ action+" from "+request.remoteAddress()+" "+threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_ORIGIN)+" via "+threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_CHANNEL_TYPE)+" "+threadContext.getHeaders());
listener.onFailure(new ElasticsearchSecurityException("No user found for "+action, RestStatus.INTERNAL_SERVER_ERROR));
return;
}

final PrivilegesEvaluator eval = evalp;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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.amazon.opendistroforelasticsearch.security.setting;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Setting;

/**
* An abstract class to track the state of an opensearch dynamic setting.
* To instantiate for a dynamic setting, pass the Setting and the Setting's fetched value to the constructor
*
* @param <T> The type of the Setting
*/
public abstract class OpenDistroDynamicSetting<T> {
private final Setting<T> dynamicSetting;
private volatile T dynamicSettingValue;

private final Logger logger = LogManager.getLogger(getClass());

public OpenDistroDynamicSetting(Setting<T> dynamicSetting, T dynamicSettingValue) {
this.dynamicSetting = dynamicSetting;
this.dynamicSettingValue = dynamicSettingValue;
}

public void registerClusterSettingsChangeListener(final ClusterSettings clusterSettings) {
clusterSettings.addSettingsUpdateConsumer(dynamicSetting,
dynamicSettingNewValue -> {
logger.info(getClusterChangeMessage(dynamicSettingNewValue));
setDynamicSettingValue(dynamicSettingNewValue);
});
}

protected String getClusterChangeMessage(final T dynamicSettingNewValue) {
return String.format("Detected change in settings, updated cluster setting value is %s", dynamicSettingNewValue);
}

private void setDynamicSettingValue(final T dynamicSettingValue) {
this.dynamicSettingValue = dynamicSettingValue;
}

public T getDynamicSettingValue() {
return dynamicSettingValue;
}

public Setting<T> getDynamicSetting() {
return dynamicSetting;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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.amazon.opendistroforelasticsearch.security.setting;

import com.amazon.opendistroforelasticsearch.security.support.ConfigConstants;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;

public class TransportPassiveAuthSetting extends OpenDistroDynamicSetting<Boolean> {

private static final String SETTING = ConfigConstants.OPENDISTRO_SECURITY_UNSUPPORTED_PASSIVE_INTERTRANSPORT_AUTH_INITIALLY;

public TransportPassiveAuthSetting(final Settings settings) {
super(getSetting(), getSettingInitialValue(settings));
}

private static Setting<Boolean> getSetting() {
return Setting.boolSetting(
SETTING,
false,
Setting.Property.NodeScope, Setting.Property.Dynamic);
}

private static Boolean getSettingInitialValue(final Settings settings) {
return settings.getAsBoolean(SETTING, false);
}

@Override
protected String getClusterChangeMessage(final Boolean dynamicSettingNewValue) {
return String.format("Detected change in settings, cluster setting for transportPassiveAuth is %s", dynamicSettingNewValue ? "enabled" : "disabled");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ public List<TransportInterceptor> getTransportInterceptors(NamedWriteableRegistr
List<TransportInterceptor> interceptors = new ArrayList<TransportInterceptor>(1);

if(transportSSLEnabled && !client) {
interceptors.add(new OpenDistroSecuritySSLTransportInterceptor(settings, null, null, NOOP_SSL_EXCEPTION_HANDLER));
interceptors.add(new OpenDistroSecuritySSLTransportInterceptor(settings, null, null, openDistroSSLConfig, NOOP_SSL_EXCEPTION_HANDLER));
}

return interceptors;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ public class OpenDistroSSLConfig {
public OpenDistroSSLConfig(final boolean sslOnly, final boolean dualModeEnabled) {
this.sslOnly = sslOnly;
this.dualModeEnabled = dualModeEnabled;
if (this.dualModeEnabled && !this.sslOnly) {
logger.warn("opendistro_security_config.ssl_dual_mode_enabled is enabled but opendistro_security.ssl_only mode is disabled. "
+ "SSL Dual mode is supported only when security plugin is in ssl_only mode");
}
logger.info("SSL dual mode is {}", isDualModeEnabled() ? "enabled" : "disabled");
}

Expand All @@ -60,8 +56,7 @@ private void setDualModeEnabled(boolean dualModeEnabled) {
}

public boolean isDualModeEnabled() {
// currently dual mode can be enabled only when SSLOnly is enabled. This stance can change in future.
return sslOnly && dualModeEnabled;
return dualModeEnabled;
}

public boolean isSslOnlyMode() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import javax.net.ssl.SSLPeerUnverifiedException;

import com.amazon.opendistroforelasticsearch.security.support.ConfigConstants;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchException;
Expand Down Expand Up @@ -54,22 +55,26 @@ public class OpenDistroSecuritySSLRequestHandler<T extends TransportRequest>
protected final Logger log = LogManager.getLogger(this.getClass());
private final PrincipalExtractor principalExtractor;
private final SslExceptionHandler errorHandler;
private final OpenDistroSSLConfig openDistroSSLConfig;

public OpenDistroSecuritySSLRequestHandler(String action, TransportRequestHandler<T> actualHandler,
ThreadPool threadPool, final PrincipalExtractor principalExtractor, final SslExceptionHandler errorHandler) {

public OpenDistroSecuritySSLRequestHandler(String action, TransportRequestHandler<T> actualHandler,
ThreadPool threadPool, final PrincipalExtractor principalExtractor, final OpenDistroSSLConfig openDistroSSLConfig,
final SslExceptionHandler errorHandler) {
super();
this.action = action;
this.actualHandler = actualHandler;
this.threadPool = threadPool;
this.principalExtractor = principalExtractor;
this.openDistroSSLConfig = openDistroSSLConfig;
this.errorHandler = errorHandler;
}

protected ThreadContext getThreadContext() {
if(threadPool == null) {
return null;
}

return threadPool.getThreadContext();
}

Expand Down Expand Up @@ -111,6 +116,12 @@ public final void messageReceived(T request, TransportChannel channel, Task task
final SslHandler sslhandler = (SslHandler) nettyChannel.getNettyChannel().pipeline().get("ssl_server");

if (sslhandler == null) {
if (openDistroSSLConfig.isDualModeEnabled()) {
log.info("Communication in dual mode. Skipping SSL handler check");
threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_DUAL_MODE_SKIP_SECURITY, Boolean.TRUE);
messageReceivedDecorate(request, actualHandler, channel, task);
return;
}
final String msg = "No ssl handler found (SG 11)";
//log.error(msg);
final Exception exception = new ElasticsearchException(msg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,22 @@ public final class OpenDistroSecuritySSLTransportInterceptor implements Transpor
protected final ThreadPool threadPool;
protected final PrincipalExtractor principalExtractor;
protected final SslExceptionHandler errorHandler;

public OpenDistroSecuritySSLTransportInterceptor(final Settings settings, final ThreadPool threadPool,
PrincipalExtractor principalExtractor, final SslExceptionHandler errorHandler) {
protected final OpenDistroSSLConfig openDistroSSLConfig;

public OpenDistroSecuritySSLTransportInterceptor(final Settings settings, final ThreadPool threadPool,
PrincipalExtractor principalExtractor, final OpenDistroSSLConfig openDistroSSLConfig,
final SslExceptionHandler errorHandler) {
this.threadPool = threadPool;
this.principalExtractor = principalExtractor;
this.errorHandler = errorHandler;
this.openDistroSSLConfig = openDistroSSLConfig;
}

@Override
public <T extends TransportRequest> TransportRequestHandler<T> interceptHandler(String action, String executor, boolean forceExecution,
TransportRequestHandler<T> actualHandler) {
return new OpenDistroSecuritySSLRequestHandler<T>(action, actualHandler, threadPool, principalExtractor, errorHandler);
return new OpenDistroSecuritySSLRequestHandler<>(action, actualHandler, threadPool, principalExtractor, openDistroSSLConfig, errorHandler);

}


Expand Down
Loading

0 comments on commit 7a08fae

Please sign in to comment.