Remove Deprecated Script Settings (#24756)

Removes all fine-grained script settings replaced by scripts.types_allowed and scripts.contexts_allowed.
This commit is contained in:
Jack Conradson 2017-05-18 13:32:46 -07:00 committed by GitHub
parent fe83df2a50
commit 1196dfb6bb
28 changed files with 163 additions and 1020 deletions

View File

@ -19,8 +19,6 @@
package org.elasticsearch.common.settings; package org.elasticsearch.common.settings;
import org.elasticsearch.action.admin.indices.close.TransportCloseIndexAction; import org.elasticsearch.action.admin.indices.close.TransportCloseIndexAction;
import org.elasticsearch.transport.RemoteClusterService;
import org.elasticsearch.transport.RemoteClusterAware;
import org.elasticsearch.action.search.TransportSearchAction; import org.elasticsearch.action.search.TransportSearchAction;
import org.elasticsearch.action.support.AutoCreateIndex; import org.elasticsearch.action.support.AutoCreateIndex;
import org.elasticsearch.action.support.DestructiveOperations; import org.elasticsearch.action.support.DestructiveOperations;
@ -88,6 +86,8 @@ import org.elasticsearch.search.SearchModule;
import org.elasticsearch.search.SearchService; import org.elasticsearch.search.SearchService;
import org.elasticsearch.search.fetch.subphase.highlight.FastVectorHighlighter; import org.elasticsearch.search.fetch.subphase.highlight.FastVectorHighlighter;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.RemoteClusterAware;
import org.elasticsearch.transport.RemoteClusterService;
import org.elasticsearch.transport.TcpTransport; import org.elasticsearch.transport.TcpTransport;
import org.elasticsearch.transport.Transport; import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
@ -304,6 +304,8 @@ public final class ClusterSettings extends AbstractScopedSettings {
ScriptService.SCRIPT_CACHE_EXPIRE_SETTING, ScriptService.SCRIPT_CACHE_EXPIRE_SETTING,
ScriptService.SCRIPT_MAX_SIZE_IN_BYTES, ScriptService.SCRIPT_MAX_SIZE_IN_BYTES,
ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE, ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE,
ScriptService.TYPES_ALLOWED_SETTING,
ScriptService.CONTEXTS_ALLOWED_SETTING,
IndicesService.INDICES_CACHE_CLEAN_INTERVAL_SETTING, IndicesService.INDICES_CACHE_CLEAN_INTERVAL_SETTING,
IndicesFieldDataCache.INDICES_FIELDDATA_CACHE_SIZE_KEY, IndicesFieldDataCache.INDICES_FIELDDATA_CACHE_SIZE_KEY,
IndicesRequestCache.INDICES_CACHE_QUERY_SIZE, IndicesRequestCache.INDICES_CACHE_QUERY_SIZE,

View File

@ -327,7 +327,6 @@ public class Node implements Closeable {
final ResourceWatcherService resourceWatcherService = new ResourceWatcherService(settings, threadPool); final ResourceWatcherService resourceWatcherService = new ResourceWatcherService(settings, threadPool);
final ScriptModule scriptModule = ScriptModule.create(settings, pluginsService.filterPlugins(ScriptPlugin.class)); final ScriptModule scriptModule = ScriptModule.create(settings, pluginsService.filterPlugins(ScriptPlugin.class));
AnalysisModule analysisModule = new AnalysisModule(this.environment, pluginsService.filterPlugins(AnalysisPlugin.class)); AnalysisModule analysisModule = new AnalysisModule(this.environment, pluginsService.filterPlugins(AnalysisPlugin.class));
additionalSettings.addAll(scriptModule.getSettings());
// this is as early as we can validate settings at this point. we already pass them to ScriptModule as well as ThreadPool // this is as early as we can validate settings at this point. we already pass them to ScriptModule as well as ThreadPool
// so we might be late here already // so we might be late here already
final SettingsModule settingsModule = new SettingsModule(this.settings, additionalSettings, additionalSettingsFilter); final SettingsModule settingsModule = new SettingsModule(this.settings, additionalSettings, additionalSettingsFilter);

View File

@ -1,150 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.script;
import org.apache.lucene.util.SetOnce;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Function;
/**
* Holds the boolean indicating the enabled mode for each of the different scripting languages available, each script source and each
* scripted operation.
*/
public class ScriptModes {
private static final String SCRIPT_SETTINGS_PREFIX = "script";
private static final String ENGINE_SETTINGS_PREFIX = "script.engine";
final Map<String, Boolean> scriptEnabled;
private static final Setting<List<String>> TYPES_ALLOWED_SETTING =
Setting.listSetting("script.types_allowed", Collections.emptyList(), Function.identity(), Setting.Property.NodeScope);
private static final Setting<List<String>> CONTEXTS_ALLOWED_SETTING =
Setting.listSetting("script.contexts_allowed", Collections.emptyList(), Function.identity(), Setting.Property.NodeScope);
private final Set<String> typesAllowed;
private final Set<String> contextsAllowed;
ScriptModes(ScriptContextRegistry scriptContextRegistry, ScriptSettings scriptSettings, Settings settings) {
HashMap<String, Boolean> scriptModes = new HashMap<>();
for (Setting<Boolean> scriptModeSetting : scriptSettings.getScriptLanguageSettings()) {
scriptModes.put(scriptModeSetting.getKey(), scriptModeSetting.get(settings));
}
this.scriptEnabled = Collections.unmodifiableMap(scriptModes);
typesAllowed = TYPES_ALLOWED_SETTING.exists(settings) ? new HashSet<>() : null;
if (typesAllowed != null) {
for (String settingType : TYPES_ALLOWED_SETTING.get(settings)) {
boolean found = false;
for (ScriptType scriptType : ScriptType.values()) {
if (scriptType.getName().equals(settingType)) {
found = true;
typesAllowed.add(settingType);
break;
}
}
if (!found) {
throw new IllegalArgumentException(
"unknown script type [" + settingType + "] found in setting [" + TYPES_ALLOWED_SETTING.getKey() + "].");
}
}
}
contextsAllowed = CONTEXTS_ALLOWED_SETTING.exists(settings) ? new HashSet<>() : null;
if (contextsAllowed != null) {
for (String settingContext : CONTEXTS_ALLOWED_SETTING.get(settings)) {
if (scriptContextRegistry.isSupportedContext(settingContext)) {
contextsAllowed.add(settingContext);
} else {
throw new IllegalArgumentException(
"unknown script context [" + settingContext + "] found in setting [" + CONTEXTS_ALLOWED_SETTING.getKey() + "].");
}
}
}
}
/**
* Returns the script mode for a script of a certain written in a certain language,
* of a certain type and executing as part of a specific operation/api.
*
* @param lang the language that the script is written in
* @param scriptType the type of the script
* @param scriptContext the operation that requires the execution of the script
* @return whether scripts are enabled (true) or disabled (false)
*/
public boolean getScriptEnabled(String lang, ScriptType scriptType, ScriptContext scriptContext) {
if (typesAllowed != null && typesAllowed.contains(scriptType.getName()) == false) {
throw new IllegalArgumentException("[" + scriptType.getName() + "] scripts cannot be executed");
}
if (contextsAllowed != null && contextsAllowed.contains(scriptContext.getKey()) == false) {
throw new IllegalArgumentException("[" + scriptContext.getKey() + "] scripts cannot be executed");
}
Boolean scriptMode = scriptEnabled.get(getKey(lang, scriptType, scriptContext));
if (scriptMode == null) {
throw new IllegalArgumentException("script mode not found for lang [" + lang + "], script_type [" + scriptType + "], operation [" + scriptContext.getKey() + "]");
}
return scriptMode;
}
static String operationKey(ScriptContext scriptContext) {
return SCRIPT_SETTINGS_PREFIX + "." + scriptContext.getKey();
}
static String sourceKey(ScriptType scriptType) {
return SCRIPT_SETTINGS_PREFIX + "." + scriptType.getName();
}
static String getGlobalKey(String lang, ScriptType scriptType) {
return ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType;
}
static String getKey(String lang, ScriptType scriptType, ScriptContext scriptContext) {
return ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey();
}
@Override
public String toString() {
//order settings by key before printing them out, for readability
TreeMap<String, Boolean> scriptModesTreeMap = new TreeMap<>();
scriptModesTreeMap.putAll(scriptEnabled);
StringBuilder stringBuilder = new StringBuilder();
for (Map.Entry<String, Boolean> stringScriptModeEntry : scriptModesTreeMap.entrySet()) {
stringBuilder.append(stringScriptModeEntry.getKey()).append(": ").append(stringScriptModeEntry.getValue()).append("\n");
}
return stringBuilder.toString();
}
}

View File

@ -20,24 +20,18 @@
package org.elasticsearch.script; package org.elasticsearch.script;
import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.plugins.ScriptPlugin; import org.elasticsearch.plugins.ScriptPlugin;
import org.elasticsearch.watcher.ResourceWatcherService;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* Manages building {@link ScriptService} and {@link ScriptSettings} from a list of plugins. * Manages building {@link ScriptService}.
*/ */
public class ScriptModule { public class ScriptModule {
private final ScriptSettings scriptSettings;
private final ScriptService scriptService; private final ScriptService scriptService;
/** /**
@ -59,21 +53,13 @@ public class ScriptModule {
List<ScriptContext.Plugin> customScriptContexts) { List<ScriptContext.Plugin> customScriptContexts) {
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customScriptContexts); ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customScriptContexts);
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(scriptEngines); ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(scriptEngines);
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
try { try {
scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry, scriptSettings); scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Couldn't setup ScriptService", e); throw new RuntimeException("Couldn't setup ScriptService", e);
} }
} }
/**
* Extra settings for scripts.
*/
public List<Setting<?>> getSettings() {
return scriptSettings.getSettings();
}
/** /**
* Service responsible for managing scripts. * Service responsible for managing scripts.
*/ */

View File

@ -19,12 +19,6 @@
package org.elasticsearch.script; package org.elasticsearch.script;
import java.io.Closeable;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.IOUtils;
import org.elasticsearch.ResourceNotFoundException; import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
@ -41,7 +35,6 @@ import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.breaker.CircuitBreakingException; import org.elasticsearch.common.breaker.CircuitBreakingException;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.cache.Cache; import org.elasticsearch.common.cache.Cache;
import org.elasticsearch.common.cache.CacheBuilder; import org.elasticsearch.common.cache.CacheBuilder;
import org.elasticsearch.common.cache.RemovalListener; import org.elasticsearch.common.cache.RemovalListener;
@ -55,6 +48,16 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.search.lookup.SearchLookup;
import org.elasticsearch.template.CompiledTemplate; import org.elasticsearch.template.CompiledTemplate;
import java.io.Closeable;
import java.io.IOException;
import java.util.Collections;
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;
public class ScriptService extends AbstractComponent implements Closeable, ClusterStateListener { public class ScriptService extends AbstractComponent implements Closeable, ClusterStateListener {
static final String DISABLE_DYNAMIC_SCRIPTING_SETTING = "script.disable_dynamic"; static final String DISABLE_DYNAMIC_SCRIPTING_SETTING = "script.disable_dynamic";
@ -68,11 +71,20 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
public static final Setting<Integer> SCRIPT_MAX_COMPILATIONS_PER_MINUTE = public static final Setting<Integer> SCRIPT_MAX_COMPILATIONS_PER_MINUTE =
Setting.intSetting("script.max_compilations_per_minute", 15, 0, Property.Dynamic, Property.NodeScope); Setting.intSetting("script.max_compilations_per_minute", 15, 0, Property.Dynamic, Property.NodeScope);
public static final String ALLOW_NONE = "none";
public static final Setting<List<String>> TYPES_ALLOWED_SETTING =
Setting.listSetting("script.types_allowed", Collections.emptyList(), Function.identity(), Setting.Property.NodeScope);
public static final Setting<List<String>> CONTEXTS_ALLOWED_SETTING =
Setting.listSetting("script.contexts_allowed", Collections.emptyList(), Function.identity(), Setting.Property.NodeScope);
private final Set<String> typesAllowed;
private final Set<String> contextsAllowed;
private final Map<String, ScriptEngine> engines; private final Map<String, ScriptEngine> engines;
private final Cache<CacheKey, CompiledScript> cache; private final Cache<CacheKey, CompiledScript> cache;
private final ScriptModes scriptModes;
private final ScriptContextRegistry scriptContextRegistry; private final ScriptContextRegistry scriptContextRegistry;
private final ScriptMetrics scriptMetrics = new ScriptMetrics(); private final ScriptMetrics scriptMetrics = new ScriptMetrics();
@ -84,18 +96,87 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
private double scriptsPerMinCounter; private double scriptsPerMinCounter;
private double compilesAllowedPerNano; private double compilesAllowedPerNano;
public ScriptService(Settings settings, ScriptEngineRegistry scriptEngineRegistry, public ScriptService(Settings settings, ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry) throws IOException {
ScriptContextRegistry scriptContextRegistry, ScriptSettings scriptSettings) throws IOException {
super(settings); super(settings);
Objects.requireNonNull(settings);
Objects.requireNonNull(scriptEngineRegistry); Objects.requireNonNull(scriptEngineRegistry);
Objects.requireNonNull(scriptContextRegistry); Objects.requireNonNull(scriptContextRegistry);
Objects.requireNonNull(scriptSettings);
if (Strings.hasLength(settings.get(DISABLE_DYNAMIC_SCRIPTING_SETTING))) { if (Strings.hasLength(settings.get(DISABLE_DYNAMIC_SCRIPTING_SETTING))) {
throw new IllegalArgumentException(DISABLE_DYNAMIC_SCRIPTING_SETTING + " is not a supported setting, replace with fine-grained script settings. \n" + throw new IllegalArgumentException(DISABLE_DYNAMIC_SCRIPTING_SETTING + " is not a supported setting, replace with fine-grained script settings. \n" +
"Dynamic scripts can be enabled for all languages and all operations by replacing `script.disable_dynamic: false` with `script.inline: true` and `script.stored: true` in elasticsearch.yml"); "Dynamic scripts can be enabled for all languages and all operations not using `script.disable_dynamic: false` in elasticsearch.yml");
}
this.typesAllowed = TYPES_ALLOWED_SETTING.exists(settings) ? new HashSet<>() : null;
if (this.typesAllowed != null) {
List<String> typesAllowedList = TYPES_ALLOWED_SETTING.get(settings);
if (typesAllowedList.isEmpty()) {
throw new IllegalArgumentException(
"must specify at least one script type or none for setting [" + TYPES_ALLOWED_SETTING.getKey() + "].");
}
for (String settingType : typesAllowedList) {
if (ALLOW_NONE.equals(settingType)) {
if (typesAllowedList.size() != 1) {
throw new IllegalArgumentException("cannot specify both [" + ALLOW_NONE + "]" +
" and other script types for setting [" + TYPES_ALLOWED_SETTING.getKey() + "].");
} else {
break;
}
}
boolean found = false;
for (ScriptType scriptType : ScriptType.values()) {
if (scriptType.getName().equals(settingType)) {
found = true;
this.typesAllowed.add(settingType);
break;
}
}
if (found == false) {
throw new IllegalArgumentException(
"unknown script type [" + settingType + "] found in setting [" + TYPES_ALLOWED_SETTING.getKey() + "].");
}
}
}
this.contextsAllowed = CONTEXTS_ALLOWED_SETTING.exists(settings) ? new HashSet<>() : null;
if (this.contextsAllowed != null) {
List<String> contextsAllowedList = CONTEXTS_ALLOWED_SETTING.get(settings);
if (contextsAllowedList.isEmpty()) {
throw new IllegalArgumentException(
"must specify at least one script context or none for setting [" + CONTEXTS_ALLOWED_SETTING.getKey() + "].");
}
for (String settingContext : contextsAllowedList) {
if (ALLOW_NONE.equals(settingContext)) {
if (contextsAllowedList.size() != 1) {
throw new IllegalArgumentException("cannot specify both [" + ALLOW_NONE + "]" +
" and other script contexts for setting [" + CONTEXTS_ALLOWED_SETTING.getKey() + "].");
} else {
break;
}
}
if (scriptContextRegistry.isSupportedContext(settingContext)) {
this.contextsAllowed.add(settingContext);
} else {
throw new IllegalArgumentException(
"unknown script context [" + settingContext + "] found in setting [" + CONTEXTS_ALLOWED_SETTING.getKey() + "].");
}
}
} }
this.scriptContextRegistry = scriptContextRegistry; this.scriptContextRegistry = scriptContextRegistry;
int cacheMaxSize = SCRIPT_CACHE_SIZE_SETTING.get(settings); int cacheMaxSize = SCRIPT_CACHE_SIZE_SETTING.get(settings);
CacheBuilder<CacheKey, CompiledScript> cacheBuilder = CacheBuilder.builder(); CacheBuilder<CacheKey, CompiledScript> cacheBuilder = CacheBuilder.builder();
@ -110,8 +191,9 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
logger.debug("using script cache with max_size [{}], expire [{}]", cacheMaxSize, cacheExpire); logger.debug("using script cache with max_size [{}], expire [{}]", cacheMaxSize, cacheExpire);
this.cache = cacheBuilder.removalListener(new ScriptCacheRemovalListener()).build(); this.cache = cacheBuilder.removalListener(new ScriptCacheRemovalListener()).build();
this.engines = scriptEngineRegistry.getRegisteredLanguages(); this.engines = scriptEngineRegistry.getRegisteredLanguages();
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, settings);
this.lastInlineCompileTime = System.nanoTime(); this.lastInlineCompileTime = System.nanoTime();
this.setMaxCompilationsPerMinute(SCRIPT_MAX_COMPILATIONS_PER_MINUTE.get(settings)); this.setMaxCompilationsPerMinute(SCRIPT_MAX_COMPILATIONS_PER_MINUTE.get(settings));
} }
@ -194,9 +276,16 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
ScriptEngine scriptEngine = getEngine(lang); ScriptEngine scriptEngine = getEngine(lang);
if (canExecuteScript(lang, type, scriptContext) == false) { if (isTypeEnabled(type) == false) {
throw new IllegalStateException("scripts of type [" + script.getType() + "]," + throw new IllegalArgumentException("cannot execute [" + type + "] scripts");
" operation [" + scriptContext.getKey() + "] and lang [" + lang + "] are disabled"); }
if (scriptContextRegistry.isSupportedContext(scriptContext.getKey()) == false) {
throw new IllegalArgumentException("script context [" + scriptContext.getKey() + "] not supported");
}
if (isContextEnabled(scriptContext) == false) {
throw new IllegalArgumentException("cannot execute scripts using [" + scriptContext.getKey() + "] context");
} }
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
@ -288,6 +377,18 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
return engines.containsKey(lang); return engines.containsKey(lang);
} }
public boolean isTypeEnabled(ScriptType scriptType) {
return typesAllowed == null || typesAllowed.contains(scriptType.getName());
}
public boolean isContextEnabled(ScriptContext scriptContext) {
return contextsAllowed == null || contextsAllowed.contains(scriptContext.getKey());
}
public boolean isAnyContextEnabled() {
return contextsAllowed == null || contextsAllowed.isEmpty() == false;
}
StoredScriptSource getScriptFromClusterState(String id, String lang) { StoredScriptSource getScriptFromClusterState(String id, String lang) {
if (lang != null && isLangSupported(lang) == false) { if (lang != null && isLangSupported(lang) == false) {
throw new IllegalArgumentException("unable to get stored script with unsupported lang [" + lang + "]"); throw new IllegalArgumentException("unable to get stored script with unsupported lang [" + lang + "]");
@ -328,16 +429,19 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
try { try {
ScriptEngine scriptEngine = getEngine(source.getLang()); ScriptEngine scriptEngine = getEngine(source.getLang());
if (isAnyScriptContextEnabled(source.getLang(), ScriptType.STORED)) { if (isTypeEnabled(ScriptType.STORED) == false) {
throw new IllegalArgumentException(
"cannot put [" + ScriptType.STORED + "] script, [" + ScriptType.STORED + "] scripts are not enabled");
} else if (isAnyContextEnabled() == false) {
throw new IllegalArgumentException(
"cannot put [" + ScriptType.STORED + "] script, no script contexts are enabled");
} else {
Object compiled = scriptEngine.compile(request.id(), source.getCode(), Collections.emptyMap()); Object compiled = scriptEngine.compile(request.id(), source.getCode(), Collections.emptyMap());
if (compiled == null) { if (compiled == null) {
throw new IllegalArgumentException("failed to parse/compile stored script [" + request.id() + "]" + throw new IllegalArgumentException("failed to parse/compile stored script [" + request.id() + "]" +
(source.getCode() == null ? "" : " using code [" + source.getCode() + "]")); (source.getCode() == null ? "" : " using code [" + source.getCode() + "]"));
} }
} else {
throw new IllegalArgumentException(
"cannot put stored script [" + request.id() + "], stored scripts cannot be run under any context");
} }
} catch (ScriptException good) { } catch (ScriptException good) {
throw good; throw good;
@ -422,23 +526,6 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
return getEngine(compiledScript.lang()).search(compiledScript, lookup, params); return getEngine(compiledScript.lang()).search(compiledScript, lookup, params);
} }
private boolean isAnyScriptContextEnabled(String lang, ScriptType scriptType) {
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
if (canExecuteScript(lang, scriptType, scriptContext)) {
return true;
}
}
return false;
}
private boolean canExecuteScript(String lang, ScriptType scriptType, ScriptContext scriptContext) {
assert lang != null;
if (scriptContextRegistry.isSupportedContext(scriptContext.getKey()) == false) {
throw new IllegalArgumentException("script context [" + scriptContext.getKey() + "] not supported");
}
return scriptModes.getScriptEnabled(lang, scriptType, scriptContext);
}
public ScriptStats stats() { public ScriptStats stats() {
return scriptMetrics.stats(); return scriptMetrics.stats();
} }

View File

@ -1,155 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.script;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public class ScriptSettings {
private static final Map<ScriptType, Setting<Boolean>> SCRIPT_TYPE_SETTING_MAP;
static {
Map<ScriptType, Setting<Boolean>> scriptTypeSettingMap = new EnumMap<>(ScriptType.class);
for (ScriptType scriptType : ScriptType.values()) {
scriptTypeSettingMap.put(scriptType, Setting.boolSetting(
ScriptModes.sourceKey(scriptType),
scriptType.isDefaultEnabled(),
Property.NodeScope,
Property.Deprecated));
}
SCRIPT_TYPE_SETTING_MAP = Collections.unmodifiableMap(scriptTypeSettingMap);
}
private final Map<ScriptContext, Setting<Boolean>> scriptContextSettingMap;
private final List<Setting<Boolean>> scriptLanguageSettings;
public ScriptSettings(ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry) {
Map<ScriptContext, Setting<Boolean>> scriptContextSettingMap = contextSettings(scriptContextRegistry);
this.scriptContextSettingMap = Collections.unmodifiableMap(scriptContextSettingMap);
List<Setting<Boolean>> scriptLanguageSettings = languageSettings(SCRIPT_TYPE_SETTING_MAP, scriptContextSettingMap, scriptEngineRegistry, scriptContextRegistry);
this.scriptLanguageSettings = Collections.unmodifiableList(scriptLanguageSettings);
}
private static Map<ScriptContext, Setting<Boolean>> contextSettings(ScriptContextRegistry scriptContextRegistry) {
Map<ScriptContext, Setting<Boolean>> scriptContextSettingMap = new HashMap<>();
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
scriptContextSettingMap.put(scriptContext,
Setting.boolSetting(ScriptModes.operationKey(scriptContext), false, Property.NodeScope, Property.Deprecated));
}
return scriptContextSettingMap;
}
private static List<Setting<Boolean>> languageSettings(Map<ScriptType, Setting<Boolean>> scriptTypeSettingMap,
Map<ScriptContext, Setting<Boolean>> scriptContextSettingMap,
ScriptEngineRegistry scriptEngineRegistry,
ScriptContextRegistry scriptContextRegistry) {
final List<Setting<Boolean>> scriptModeSettings = new ArrayList<>();
for (final Class<? extends ScriptEngine> scriptEngineService : scriptEngineRegistry.getRegisteredScriptEngineServices()) {
final String language = scriptEngineRegistry.getLanguage(scriptEngineService);
for (final ScriptType scriptType : ScriptType.values()) {
// Top level, like "script.engine.groovy.inline"
final boolean defaultNonFileScriptMode = scriptEngineRegistry.getDefaultInlineScriptEnableds().get(language);
boolean defaultLangAndType = defaultNonFileScriptMode;
// Files are treated differently because they are never default-deny
final boolean defaultIfNothingSet = defaultLangAndType;
Function<Settings, String> defaultLangAndTypeFn = settings -> {
final Setting<Boolean> globalTypeSetting = scriptTypeSettingMap.get(scriptType);
final Setting<Boolean> langAndTypeSetting = Setting.boolSetting(ScriptModes.getGlobalKey(language, scriptType),
defaultIfNothingSet, Property.NodeScope, Property.Deprecated);
if (langAndTypeSetting.exists(settings)) {
// fine-grained e.g. script.engine.groovy.inline
return langAndTypeSetting.get(settings).toString();
} else if (globalTypeSetting.exists(settings)) {
// global type - script.inline
return globalTypeSetting.get(settings).toString();
} else {
return Boolean.toString(defaultIfNothingSet);
}
};
// Setting for something like "script.engine.groovy.inline"
final Setting<Boolean> langAndTypeSetting = Setting.boolSetting(ScriptModes.getGlobalKey(language, scriptType),
defaultLangAndTypeFn, Property.NodeScope, Property.Deprecated);
scriptModeSettings.add(langAndTypeSetting);
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
final String langAndTypeAndContextName = ScriptModes.getKey(language, scriptType, scriptContext);
// A function that, given a setting, will return what the default should be. Since the fine-grained script settings
// read from a bunch of different places this is implemented in this way.
Function<Settings, String> defaultSettingFn = settings -> {
final Setting<Boolean> globalOpSetting = scriptContextSettingMap.get(scriptContext);
final Setting<Boolean> globalTypeSetting = scriptTypeSettingMap.get(scriptType);
final Setting<Boolean> langAndTypeAndContextSetting = Setting.boolSetting(langAndTypeAndContextName,
defaultIfNothingSet, Property.NodeScope, Property.Deprecated);
// fallback logic for script mode settings
if (langAndTypeAndContextSetting.exists(settings)) {
// like: "script.engine.groovy.inline.aggs: true"
return langAndTypeAndContextSetting.get(settings).toString();
} else if (langAndTypeSetting.exists(settings)) {
// like: "script.engine.groovy.inline: true"
return langAndTypeSetting.get(settings).toString();
} else if (globalOpSetting.exists(settings)) {
// like: "script.aggs: true"
return globalOpSetting.get(settings).toString();
} else if (globalTypeSetting.exists(settings)) {
// like: "script.inline: true"
return globalTypeSetting.get(settings).toString();
} else {
// Nothing is set!
return Boolean.toString(defaultIfNothingSet);
}
};
// The actual setting for finest grained script settings
Setting<Boolean> setting =
Setting.boolSetting(langAndTypeAndContextName, defaultSettingFn, Property.NodeScope, Property.Deprecated);
scriptModeSettings.add(setting);
}
}
}
return scriptModeSettings;
}
public List<Setting<?>> getSettings() {
List<Setting<?>> settings = new ArrayList<>();
settings.addAll(SCRIPT_TYPE_SETTING_MAP.values());
settings.addAll(scriptContextSettingMap.values());
settings.addAll(scriptLanguageSettings);
return settings;
}
public Iterable<Setting<Boolean>> getScriptLanguageSettings() {
return scriptLanguageSettings;
}
}

View File

@ -28,8 +28,8 @@ import java.io.IOException;
/** /**
* ScriptType represents the way a script is stored and retrieved from the {@link ScriptService}. * ScriptType represents the way a script is stored and retrieved from the {@link ScriptService}.
* It's also used to by {@link ScriptSettings} and {@link ScriptModes} to determine whether or not * It's also used to by {@link ScriptService} to determine whether or not a {@link Script} is
* a {@link Script} is allowed to be executed based on both default and user-defined settings. * allowed to be executed based on both default and user-defined settings.
*/ */
public enum ScriptType implements Writeable { public enum ScriptType implements Writeable {

View File

@ -45,7 +45,6 @@ import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContextRegistry; import org.elasticsearch.script.ScriptContextRegistry;
import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptSettings;
import org.elasticsearch.script.ScriptType; import org.elasticsearch.script.ScriptType;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.RandomObjects; import org.elasticsearch.test.RandomObjects;
@ -64,7 +63,6 @@ import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.common.xcontent.XContentHelper.toXContent; import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
import static org.elasticsearch.common.xcontent.XContentHelper.update;
import static org.elasticsearch.script.MockScriptEngine.mockInlineScript; import static org.elasticsearch.script.MockScriptEngine.mockInlineScript;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContaining;
@ -145,15 +143,12 @@ public class UpdateRequestTests extends ESTestCase {
final ScriptEngineRegistry scriptEngineRegistry = final ScriptEngineRegistry scriptEngineRegistry =
new ScriptEngineRegistry(singletonList(engine)); new ScriptEngineRegistry(singletonList(engine));
final ScriptSettings scriptSettings =
new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
final ResourceWatcherService watcherService = final ResourceWatcherService watcherService =
new ResourceWatcherService(baseSettings, null); new ResourceWatcherService(baseSettings, null);
ScriptService scriptService = new ScriptService( ScriptService scriptService = new ScriptService(
baseSettings, baseSettings,
scriptEngineRegistry, scriptEngineRegistry,
scriptContextRegistry, scriptContextRegistry);
scriptSettings);
final Settings settings = settings(Version.CURRENT).build(); final Settings settings = settings(Version.CURRENT).build();
updateHelper = new UpdateHelper(settings, scriptService); updateHelper = new UpdateHelper(settings, scriptService);

View File

@ -70,7 +70,6 @@ import org.elasticsearch.indices.mapper.MapperRegistry;
import org.elasticsearch.script.ScriptContextRegistry; import org.elasticsearch.script.ScriptContextRegistry;
import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptSettings;
import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.test.ClusterServiceUtils; import org.elasticsearch.test.ClusterServiceUtils;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
@ -130,8 +129,7 @@ public class IndexModuleTests extends ESTestCase {
bigArrays = new BigArrays(settings, circuitBreakerService); bigArrays = new BigArrays(settings, circuitBreakerService);
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(emptyList()); ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(emptyList());
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry);
scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
clusterService = ClusterServiceUtils.createClusterService(threadPool); clusterService = ClusterServiceUtils.createClusterService(threadPool);
nodeEnvironment = new NodeEnvironment(settings, environment); nodeEnvironment = new NodeEnvironment(settings, environment);
mapperRegistry = new IndicesModule(Collections.emptyList()).getMapperRegistry(); mapperRegistry = new IndicesModule(Collections.emptyList()).getMapperRegistry();

View File

@ -23,7 +23,6 @@ import org.elasticsearch.cluster.ClusterChangedEvent;
import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.settings.Setting;
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.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
@ -32,21 +31,14 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import static org.hamcrest.Matchers.containsString;
public class ScriptContextTests extends ESTestCase { public class ScriptContextTests extends ESTestCase {
private static final String PLUGIN_NAME = "testplugin"; private static final String PLUGIN_NAME = "testplugin";
private static final String SCRIPT_PLUGIN_CUSTOM_SETTING = "script." + PLUGIN_NAME + "_custom_globally_disabled_op";
private static final String SCRIPT_ENGINE_CUSTOM_SETTING = "script.engine." + MockScriptEngine.NAME + ".inline." + PLUGIN_NAME + "_custom_exp_disabled_op";
private ScriptSettings scriptSettings;
ScriptService makeScriptService() throws Exception { ScriptService makeScriptService() throws Exception {
Settings settings = Settings.builder() Settings settings = Settings.builder()
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir()) .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
.put(SCRIPT_PLUGIN_CUSTOM_SETTING, "false") .put("script.contexts_allowed", "search, aggs, testplugin_custom_op")
.put(SCRIPT_ENGINE_CUSTOM_SETTING, "false")
.build(); .build();
MockScriptEngine scriptEngine = new MockScriptEngine(MockScriptEngine.NAME, Collections.singletonMap("1", script -> "1")); MockScriptEngine scriptEngine = new MockScriptEngine(MockScriptEngine.NAME, Collections.singletonMap("1", script -> "1"));
@ -56,8 +48,7 @@ public class ScriptContextTests extends ESTestCase {
new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"), new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"),
new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op")); new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op"));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts); ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts);
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); ScriptService scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry);
ScriptService scriptService = new ScriptService(settings, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
ClusterState empty = ClusterState.builder(new ClusterName("_name")).build(); ClusterState empty = ClusterState.builder(new ClusterName("_name")).build();
ScriptMetaData smd = empty.metaData().custom(ScriptMetaData.TYPE); ScriptMetaData smd = empty.metaData().custom(ScriptMetaData.TYPE);
@ -69,8 +60,6 @@ public class ScriptContextTests extends ESTestCase {
return scriptService; return scriptService;
} }
public void testCustomGlobalScriptContextSettings() throws Exception { public void testCustomGlobalScriptContextSettings() throws Exception {
ScriptService scriptService = makeScriptService(); ScriptService scriptService = makeScriptService();
for (ScriptType scriptType : ScriptType.values()) { for (ScriptType scriptType : ScriptType.values()) {
@ -78,12 +67,10 @@ public class ScriptContextTests extends ESTestCase {
Script script = new Script(scriptType, MockScriptEngine.NAME, "1", Collections.emptyMap()); Script script = new Script(scriptType, MockScriptEngine.NAME, "1", Collections.emptyMap());
scriptService.compile(script, new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op")); scriptService.compile(script, new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op"));
fail("script compilation should have been rejected"); fail("script compilation should have been rejected");
} catch (IllegalStateException e) { } catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("scripts of type [" + scriptType + "], operation [" + PLUGIN_NAME + "_custom_globally_disabled_op] and lang [" + MockScriptEngine.NAME + "] are disabled")); assertTrue(e.getMessage(), e.getMessage().contains("cannot execute scripts using [" + PLUGIN_NAME + "_custom_globally_disabled_op] context"));
} }
} }
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, SCRIPT_PLUGIN_CUSTOM_SETTING, SCRIPT_ENGINE_CUSTOM_SETTING));
} }
public void testCustomScriptContextSettings() throws Exception { public void testCustomScriptContextSettings() throws Exception {
@ -92,16 +79,14 @@ public class ScriptContextTests extends ESTestCase {
try { try {
scriptService.compile(script, new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op")); scriptService.compile(script, new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"));
fail("script compilation should have been rejected"); fail("script compilation should have been rejected");
} catch (IllegalStateException e) { } catch (IllegalArgumentException e) {
assertTrue(e.getMessage(), e.getMessage().contains("scripts of type [inline], operation [" + PLUGIN_NAME + "_custom_exp_disabled_op] and lang [" + MockScriptEngine.NAME + "] are disabled")); assertTrue(e.getMessage(), e.getMessage().contains("cannot execute scripts using [" + PLUGIN_NAME + "_custom_exp_disabled_op] context"));
} }
// still works for other script contexts // still works for other script contexts
assertNotNull(scriptService.compile(script, ScriptContext.Standard.AGGS)); assertNotNull(scriptService.compile(script, ScriptContext.Standard.AGGS));
assertNotNull(scriptService.compile(script, ScriptContext.Standard.SEARCH)); assertNotNull(scriptService.compile(script, ScriptContext.Standard.SEARCH));
assertNotNull(scriptService.compile(script, new ScriptContext.Plugin(PLUGIN_NAME, "custom_op"))); assertNotNull(scriptService.compile(script, new ScriptContext.Plugin(PLUGIN_NAME, "custom_op")));
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, SCRIPT_PLUGIN_CUSTOM_SETTING, SCRIPT_ENGINE_CUSTOM_SETTING));
} }
public void testUnknownPluginScriptContext() throws Exception { public void testUnknownPluginScriptContext() throws Exception {
@ -115,8 +100,6 @@ public class ScriptContextTests extends ESTestCase {
assertTrue(e.getMessage(), e.getMessage().contains("script context [" + PLUGIN_NAME + "_unknown] not supported")); assertTrue(e.getMessage(), e.getMessage().contains("script context [" + PLUGIN_NAME + "_unknown] not supported"));
} }
} }
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, SCRIPT_PLUGIN_CUSTOM_SETTING, SCRIPT_ENGINE_CUSTOM_SETTING));
} }
public void testUnknownCustomScriptContext() throws Exception { public void testUnknownCustomScriptContext() throws Exception {
@ -136,7 +119,5 @@ public class ScriptContextTests extends ESTestCase {
assertTrue(e.getMessage(), e.getMessage().contains("script context [test] not supported")); assertTrue(e.getMessage(), e.getMessage().contains("script context [test] not supported"));
} }
} }
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, SCRIPT_PLUGIN_CUSTOM_SETTING, SCRIPT_ENGINE_CUSTOM_SETTING));
} }
} }

View File

@ -1,254 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.script;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.search.lookup.SearchLookup;
import org.elasticsearch.test.ESTestCase;
import org.junit.After;
import org.junit.Before;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.util.Collections.unmodifiableMap;
import static org.elasticsearch.common.util.set.Sets.newHashSet;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.containsString;
// TODO: this needs to be a base test class, and all scripting engines extend it
public class ScriptModesTests extends ESTestCase {
ScriptSettings scriptSettings;
ScriptContextRegistry scriptContextRegistry;
private ScriptContext[] scriptContexts;
private Map<String, ScriptEngine> scriptEngines;
private ScriptModes scriptModes;
private Set<String> checkedSettings;
private boolean assertAllSettingsWereChecked;
private boolean assertScriptModesNonNull;
@Before
public void setupScriptEngines() {
//randomly register custom script contexts
int randomInt = randomIntBetween(0, 3);
//prevent duplicates using map
Map<String, ScriptContext.Plugin> contexts = new HashMap<>();
for (int i = 0; i < randomInt; i++) {
String plugin = randomAlphaOfLength(randomIntBetween(1, 10));
String operation = randomAlphaOfLength(randomIntBetween(1, 30));
String context = plugin + "-" + operation;
contexts.put(context, new ScriptContext.Plugin(plugin, operation));
}
scriptContextRegistry = new ScriptContextRegistry(contexts.values());
scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]);
scriptEngines = buildScriptEnginesByLangMap(newHashSet(new CustomScriptEngine()));
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(scriptEngines.values());
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
checkedSettings = new HashSet<>();
assertAllSettingsWereChecked = true;
assertScriptModesNonNull = true;
}
@After
public void assertAllSettingsWereChecked() {
if (assertScriptModesNonNull) {
assertThat(scriptModes, notNullValue());
int numberOfSettings = ScriptType.values().length * scriptContextRegistry.scriptContexts().size();
numberOfSettings += 2; // for top-level inline/store settings
assertThat(scriptModes.scriptEnabled.size(), equalTo(numberOfSettings));
if (assertAllSettingsWereChecked) {
assertThat(checkedSettings.size(), equalTo(numberOfSettings));
}
}
}
public void testDefaultSettings() {
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, Settings.EMPTY);
assertScriptModesAllOps(false, ScriptType.STORED, ScriptType.INLINE);
}
public void testMissingSetting() {
assertAllSettingsWereChecked = false;
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, Settings.EMPTY);
try {
scriptModes.getScriptEnabled("non_existing", randomFrom(ScriptType.values()), randomFrom(scriptContexts));
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("not found for lang [non_existing]"));
}
}
public void testScriptTypeGenericSettings() {
int randomInt = randomIntBetween(1, ScriptType.values().length - 1);
Set<ScriptType> randomScriptTypesSet = new HashSet<>();
boolean[] randomScriptModes = new boolean[randomInt];
for (int i = 0; i < randomInt; i++) {
boolean added = false;
while (added == false) {
added = randomScriptTypesSet.add(randomFrom(ScriptType.values()));
}
randomScriptModes[i] = randomBoolean();
}
ScriptType[] randomScriptTypes = randomScriptTypesSet.toArray(new ScriptType[randomScriptTypesSet.size()]);
List<String> deprecated = new ArrayList<>();
Settings.Builder builder = Settings.builder();
for (int i = 0; i < randomInt; i++) {
builder.put("script" + "." + randomScriptTypes[i].getName(), randomScriptModes[i]);
deprecated.add("script" + "." + randomScriptTypes[i].getName());
}
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, builder.build());
for (int i = 0; i < randomInt; i++) {
assertScriptModesAllOps(randomScriptModes[i], randomScriptTypes[i]);
}
if (randomScriptTypesSet.contains(ScriptType.STORED) == false) {
assertScriptModesAllOps(false, ScriptType.STORED);
}
if (randomScriptTypesSet.contains(ScriptType.INLINE) == false) {
assertScriptModesAllOps(false, ScriptType.INLINE);
}
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, deprecated.toArray(new String[] {})));
}
public void testScriptContextGenericSettings() {
int randomInt = randomIntBetween(1, scriptContexts.length - 1);
Set<ScriptContext> randomScriptContextsSet = new HashSet<>();
boolean[] randomScriptModes = new boolean[randomInt];
for (int i = 0; i < randomInt; i++) {
boolean added = false;
while (added == false) {
added = randomScriptContextsSet.add(randomFrom(scriptContexts));
}
randomScriptModes[i] = randomBoolean();
}
ScriptContext[] randomScriptContexts = randomScriptContextsSet.toArray(new ScriptContext[randomScriptContextsSet.size()]);
List<String> deprecated = new ArrayList<>();
Settings.Builder builder = Settings.builder();
for (int i = 0; i < randomInt; i++) {
builder.put("script" + "." + randomScriptContexts[i].getKey(), randomScriptModes[i]);
deprecated.add("script" + "." + randomScriptContexts[i].getKey());
}
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, builder.build());
for (int i = 0; i < randomInt; i++) {
assertScriptModesAllTypes(randomScriptModes[i], randomScriptContexts[i]);
}
ScriptContext[] complementOf = complementOf(randomScriptContexts);
assertScriptModes(false, new ScriptType[]{ScriptType.STORED, ScriptType.INLINE}, complementOf);
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, deprecated.toArray(new String[] {})));
}
public void testConflictingScriptTypeAndOpGenericSettings() {
ScriptContext scriptContext = randomFrom(scriptContexts);
Settings.Builder builder = Settings.builder()
.put("script." + scriptContext.getKey(), "false")
.put("script.stored", "true")
.put("script.inline", "true");
//operations generic settings have precedence over script type generic settings
this.scriptModes = new ScriptModes(scriptContextRegistry, scriptSettings, builder.build());
assertScriptModesAllTypes(false, scriptContext);
ScriptContext[] complementOf = complementOf(scriptContext);
assertScriptModes(true, new ScriptType[]{ScriptType.STORED}, complementOf);
assertScriptModes(true, new ScriptType[]{ScriptType.INLINE}, complementOf);
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(
scriptSettings, "script." + scriptContext.getKey(), "script.stored", "script.inline"));
}
private void assertScriptModesAllOps(boolean expectedScriptEnabled, ScriptType... scriptTypes) {
assertScriptModes(expectedScriptEnabled, scriptTypes, scriptContexts);
}
private void assertScriptModesAllTypes(boolean expectedScriptEnabled, ScriptContext... scriptContexts) {
assertScriptModes(expectedScriptEnabled, ScriptType.values(), scriptContexts);
}
private void assertScriptModes(boolean expectedScriptEnabled, ScriptType[] scriptTypes, ScriptContext... scriptContexts) {
assert scriptTypes.length > 0;
assert scriptContexts.length > 0;
for (ScriptType scriptType : scriptTypes) {
checkedSettings.add("script.engine.custom." + scriptType);
for (ScriptContext scriptContext : scriptContexts) {
assertThat("custom." + scriptType + "." + scriptContext.getKey() + " doesn't have the expected value",
scriptModes.getScriptEnabled("custom", scriptType, scriptContext), equalTo(expectedScriptEnabled));
checkedSettings.add("custom." + scriptType + "." + scriptContext);
}
}
}
private ScriptContext[] complementOf(ScriptContext... scriptContexts) {
Map<String, ScriptContext> copy = new HashMap<>();
for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
copy.put(scriptContext.getKey(), scriptContext);
}
for (ScriptContext scriptContext : scriptContexts) {
copy.remove(scriptContext.getKey());
}
return copy.values().toArray(new ScriptContext[copy.size()]);
}
static Map<String, ScriptEngine> buildScriptEnginesByLangMap(Set<ScriptEngine> scriptEngines) {
Map<String, ScriptEngine> builder = new HashMap<>();
for (ScriptEngine scriptEngine : scriptEngines) {
String type = scriptEngine.getType();
builder.put(type, scriptEngine);
}
return unmodifiableMap(builder);
}
private static class CustomScriptEngine implements ScriptEngine {
public static final String NAME = "custom";
@Override
public String getType() {
return NAME;
}
@Override
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
return null;
}
@Override
public ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars) {
return null;
}
@Override
public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, @Nullable Map<String, Object> vars) {
return null;
}
@Override
public void close() {
}
}
}

View File

@ -57,7 +57,6 @@ public class ScriptServiceTests extends ESTestCase {
private Map<String, ScriptEngine> scriptEnginesByLangMap; private Map<String, ScriptEngine> scriptEnginesByLangMap;
private ScriptEngineRegistry scriptEngineRegistry; private ScriptEngineRegistry scriptEngineRegistry;
private ScriptContextRegistry scriptContextRegistry; private ScriptContextRegistry scriptContextRegistry;
private ScriptSettings scriptSettings;
private ScriptContext[] scriptContexts; private ScriptContext[] scriptContexts;
private ScriptService scriptService; private ScriptService scriptService;
private Settings baseSettings; private Settings baseSettings;
@ -80,8 +79,6 @@ public class ScriptServiceTests extends ESTestCase {
scriptEngine = new TestEngine(); scriptEngine = new TestEngine();
dangerousScriptEngine = new TestDangerousEngine(); dangerousScriptEngine = new TestDangerousEngine();
TestEngine defaultScriptServiceEngine = new TestEngine(Script.DEFAULT_SCRIPT_LANG) {}; TestEngine defaultScriptServiceEngine = new TestEngine(Script.DEFAULT_SCRIPT_LANG) {};
scriptEnginesByLangMap = ScriptModesTests.buildScriptEnginesByLangMap(
new HashSet<>(Arrays.asList(scriptEngine, defaultScriptServiceEngine)));
//randomly register custom script contexts //randomly register custom script contexts
int randomInt = randomIntBetween(0, 3); int randomInt = randomIntBetween(0, 3);
//prevent duplicates using map //prevent duplicates using map
@ -101,15 +98,13 @@ public class ScriptServiceTests extends ESTestCase {
scriptEngineRegistry = new ScriptEngineRegistry(Arrays.asList(scriptEngine, dangerousScriptEngine, scriptEngineRegistry = new ScriptEngineRegistry(Arrays.asList(scriptEngine, dangerousScriptEngine,
defaultScriptServiceEngine)); defaultScriptServiceEngine));
scriptContextRegistry = new ScriptContextRegistry(contexts.values()); scriptContextRegistry = new ScriptContextRegistry(contexts.values());
scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]); scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]);
logger.info("--> setup script service"); logger.info("--> setup script service");
} }
private void buildScriptService(Settings additionalSettings) throws IOException { private void buildScriptService(Settings additionalSettings) throws IOException {
Settings finalSettings = Settings.builder().put(baseSettings).put(additionalSettings).build(); Settings finalSettings = Settings.builder().put(baseSettings).put(additionalSettings).build();
// TODO: scriptService = new ScriptService(finalSettings, scriptEngineRegistry, scriptContextRegistry) {
scriptService = new ScriptService(finalSettings, scriptEngineRegistry, scriptContextRegistry, scriptSettings) {
@Override @Override
StoredScriptSource getScriptFromClusterState(String id, String lang) { StoredScriptSource getScriptFromClusterState(String id, String lang) {
//mock the script that gets retrieved from an index //mock the script that gets retrieved from an index
@ -179,33 +174,25 @@ public class ScriptServiceTests extends ESTestCase {
public void testAllowSomeScriptTypeSettings() throws IOException { public void testAllowSomeScriptTypeSettings() throws IOException {
Settings.Builder builder = Settings.builder(); Settings.Builder builder = Settings.builder();
builder.put("script.types_allowed", "inline"); builder.put("script.types_allowed", "inline");
builder.put("script.engine.painless.stored", false);
buildScriptService(builder.build()); buildScriptService(builder.build());
assertCompileAccepted("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH); assertCompileAccepted("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH);
assertCompileRejected("painless", "script", ScriptType.STORED, ScriptContext.Standard.SEARCH); assertCompileRejected("painless", "script", ScriptType.STORED, ScriptContext.Standard.SEARCH);
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.engine.painless.stored"));
} }
public void testAllowSomeScriptContextSettings() throws IOException { public void testAllowSomeScriptContextSettings() throws IOException {
Settings.Builder builder = Settings.builder(); Settings.Builder builder = Settings.builder();
builder.put("script.contexts_allowed", "search, aggs"); builder.put("script.contexts_allowed", "search, aggs");
builder.put("script.update", false);
buildScriptService(builder.build()); buildScriptService(builder.build());
assertCompileAccepted("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH); assertCompileAccepted("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH);
assertCompileAccepted("painless", "script", ScriptType.INLINE, ScriptContext.Standard.AGGS); assertCompileAccepted("painless", "script", ScriptType.INLINE, ScriptContext.Standard.AGGS);
assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.UPDATE); assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.UPDATE);
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.update"));
} }
public void testAllowNoScriptTypeSettings() throws IOException { public void testAllowNoScriptTypeSettings() throws IOException {
Settings.Builder builder = Settings.builder(); Settings.Builder builder = Settings.builder();
builder.put("script.types_allowed", ""); builder.put("script.types_allowed", "none");
buildScriptService(builder.build()); buildScriptService(builder.build());
assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH); assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH);
@ -214,7 +201,7 @@ public class ScriptServiceTests extends ESTestCase {
public void testAllowNoScriptContextSettings() throws IOException { public void testAllowNoScriptContextSettings() throws IOException {
Settings.Builder builder = Settings.builder(); Settings.Builder builder = Settings.builder();
builder.put("script.contexts_allowed", ""); builder.put("script.contexts_allowed", "none");
buildScriptService(builder.build()); buildScriptService(builder.build());
assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH); assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.SEARCH);
@ -223,109 +210,6 @@ public class ScriptServiceTests extends ESTestCase {
assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.INGEST); assertCompileRejected("painless", "script", ScriptType.INLINE, ScriptContext.Standard.INGEST);
} }
public void testDefaultBehaviourFineGrainedSettings() throws IOException {
Settings.Builder builder = Settings.builder();
buildScriptService(builder.build());
for (ScriptContext scriptContext : scriptContexts) {
assertCompileRejected("dtest", "script", ScriptType.INLINE, scriptContext);
assertCompileRejected("dtest", "script", ScriptType.STORED, scriptContext);
}
}
public void testFineGrainedSettings() throws IOException {
//collect the fine-grained settings to set for this run
int numScriptSettings = randomIntBetween(0, ScriptType.values().length);
Map<ScriptType, Boolean> scriptSourceSettings = new HashMap<>();
for (int i = 0; i < numScriptSettings; i++) {
ScriptType scriptType;
do {
scriptType = randomFrom(ScriptType.values());
} while (scriptSourceSettings.containsKey(scriptType));
scriptSourceSettings.put(scriptType, randomBoolean());
}
int numScriptContextSettings = randomIntBetween(0, this.scriptContextRegistry.scriptContexts().size());
Map<ScriptContext, Boolean> scriptContextSettings = new HashMap<>();
for (int i = 0; i < numScriptContextSettings; i++) {
ScriptContext scriptContext;
do {
scriptContext = randomFrom(this.scriptContexts);
} while (scriptContextSettings.containsKey(scriptContext));
scriptContextSettings.put(scriptContext, randomBoolean());
}
int numEngineSettings = randomIntBetween(0, ScriptType.values().length * scriptContexts.length);
Map<String, Boolean> engineSettings = new HashMap<>();
for (int i = 0; i < numEngineSettings; i++) {
String settingKey;
do {
ScriptType scriptType = randomFrom(ScriptType.values());
ScriptContext scriptContext = randomFrom(this.scriptContexts);
settingKey = scriptEngine.getType() + "." + scriptType + "." + scriptContext.getKey();
} while (engineSettings.containsKey(settingKey));
engineSettings.put(settingKey, randomBoolean());
}
List<String> deprecated = new ArrayList<>();
//set the selected fine-grained settings
Settings.Builder builder = Settings.builder();
for (Map.Entry<ScriptType, Boolean> entry : scriptSourceSettings.entrySet()) {
if (entry.getValue()) {
builder.put("script" + "." + entry.getKey().getName(), "true");
} else {
builder.put("script" + "." + entry.getKey().getName(), "false");
}
deprecated.add("script" + "." + entry.getKey().getName());
}
for (Map.Entry<ScriptContext, Boolean> entry : scriptContextSettings.entrySet()) {
if (entry.getValue()) {
builder.put("script" + "." + entry.getKey().getKey(), "true");
} else {
builder.put("script" + "." + entry.getKey().getKey(), "false");
}
deprecated.add("script" + "." + entry.getKey().getKey());
}
for (Map.Entry<String, Boolean> entry : engineSettings.entrySet()) {
int delimiter = entry.getKey().indexOf('.');
String part1 = entry.getKey().substring(0, delimiter);
String part2 = entry.getKey().substring(delimiter + 1);
String lang = randomFrom(scriptEnginesByLangMap.get(part1).getType());
if (entry.getValue()) {
builder.put("script.engine" + "." + lang + "." + part2, "true");
} else {
builder.put("script.engine" + "." + lang + "." + part2, "false");
}
deprecated.add("script.engine" + "." + lang + "." + part2);
}
buildScriptService(builder.build());
for (ScriptType scriptType : ScriptType.values()) {
String script = "script";
for (ScriptContext scriptContext : this.scriptContexts) {
//fallback mechanism: 1) engine specific settings 2) op based settings 3) source based settings
Boolean scriptEnabled = engineSettings.get(dangerousScriptEngine.getType() + "." + scriptType + "." + scriptContext.getKey());
if (scriptEnabled == null) {
scriptEnabled = scriptContextSettings.get(scriptContext);
}
if (scriptEnabled == null) {
scriptEnabled = scriptSourceSettings.get(scriptType);
}
if (scriptEnabled == null) {
scriptEnabled = DEFAULT_SCRIPT_ENABLED.get(scriptType);
}
String lang = dangerousScriptEngine.getType();
if (scriptEnabled) {
assertCompileAccepted(lang, script, scriptType, scriptContext);
} else {
assertCompileRejected(lang, script, scriptType, scriptContext);
}
}
}
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, deprecated.toArray(new String[] {})));
}
public void testCompileNonRegisteredContext() throws IOException { public void testCompileNonRegisteredContext() throws IOException {
buildScriptService(Settings.EMPTY); buildScriptService(Settings.EMPTY);
String pluginName; String pluginName;
@ -378,14 +262,11 @@ public class ScriptServiceTests extends ESTestCase {
public void testCompilationStatsOnCacheHit() throws IOException { public void testCompilationStatsOnCacheHit() throws IOException {
Settings.Builder builder = Settings.builder(); Settings.Builder builder = Settings.builder();
builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getKey(), 1); builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getKey(), 1);
builder.put("script.inline", "true");
buildScriptService(builder.build()); buildScriptService(builder.build());
Script script = new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()); Script script = new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap());
scriptService.compile(script, randomFrom(scriptContexts)); scriptService.compile(script, randomFrom(scriptContexts));
scriptService.compile(script, randomFrom(scriptContexts)); scriptService.compile(script, randomFrom(scriptContexts));
assertEquals(1L, scriptService.stats().getCompilations()); assertEquals(1L, scriptService.stats().getCompilations());
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.inline"));
} }
public void testIndexedScriptCountedInCompilationStats() throws IOException { public void testIndexedScriptCountedInCompilationStats() throws IOException {
@ -397,25 +278,19 @@ public class ScriptServiceTests extends ESTestCase {
public void testCacheEvictionCountedInCacheEvictionsStats() throws IOException { public void testCacheEvictionCountedInCacheEvictionsStats() throws IOException {
Settings.Builder builder = Settings.builder(); Settings.Builder builder = Settings.builder();
builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getKey(), 1); builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getKey(), 1);
builder.put("script.inline", "true");
buildScriptService(builder.build()); buildScriptService(builder.build());
scriptService.compile(new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()), randomFrom(scriptContexts)); scriptService.compile(new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()), randomFrom(scriptContexts));
scriptService.compile(new Script(ScriptType.INLINE, "test", "2+2", Collections.emptyMap()), randomFrom(scriptContexts)); scriptService.compile(new Script(ScriptType.INLINE, "test", "2+2", Collections.emptyMap()), randomFrom(scriptContexts));
assertEquals(2L, scriptService.stats().getCompilations()); assertEquals(2L, scriptService.stats().getCompilations());
assertEquals(1L, scriptService.stats().getCacheEvictions()); assertEquals(1L, scriptService.stats().getCacheEvictions());
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.inline"));
} }
public void testDefaultLanguage() throws IOException { public void testDefaultLanguage() throws IOException {
Settings.Builder builder = Settings.builder(); Settings.Builder builder = Settings.builder();
builder.put("script.inline", "true");
buildScriptService(builder.build()); buildScriptService(builder.build());
CompiledScript script = scriptService.compile( CompiledScript script = scriptService.compile(
new Script(ScriptType.INLINE, Script.DEFAULT_SCRIPT_LANG, "1 + 1", Collections.emptyMap()), randomFrom(scriptContexts)); new Script(ScriptType.INLINE, Script.DEFAULT_SCRIPT_LANG, "1 + 1", Collections.emptyMap()), randomFrom(scriptContexts));
assertEquals(script.lang(), Script.DEFAULT_SCRIPT_LANG); assertEquals(script.lang(), Script.DEFAULT_SCRIPT_LANG);
assertSettingDeprecationsAndWarnings(
ScriptSettingsTests.buildDeprecatedSettingsArray(scriptSettings, "script.inline"));
} }
public void testStoreScript() throws Exception { public void testStoreScript() throws Exception {

View File

@ -1,98 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.script;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.search.lookup.SearchLookup;
import org.elasticsearch.test.ESTestCase;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
public class ScriptSettingsTests extends ESTestCase {
public static Setting<?>[] buildDeprecatedSettingsArray(ScriptSettings scriptSettings, String... keys) {
Setting<?>[] settings = new Setting[keys.length];
int count = 0;
for (Setting<?> setting : scriptSettings.getSettings()) {
for (String key : keys) {
if (setting.getKey().equals(key)) {
settings[count++] = setting;
}
}
}
return settings;
}
public void testSettingsAreProperlyPropogated() {
ScriptEngineRegistry scriptEngineRegistry =
new ScriptEngineRegistry(Collections.singletonList(new CustomScriptEngine()));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
boolean enabled = randomBoolean();
Settings s = Settings.builder().put("script.inline", enabled).build();
for (Iterator<Setting<Boolean>> iter = scriptSettings.getScriptLanguageSettings().iterator(); iter.hasNext();) {
Setting<Boolean> setting = iter.next();
if (setting.getKey().endsWith(".inline")) {
assertThat("inline settings should have propagated", setting.get(s), equalTo(enabled));
assertThat(setting.getDefaultRaw(s), equalTo(Boolean.toString(enabled)));
}
}
assertSettingDeprecationsAndWarnings(buildDeprecatedSettingsArray(scriptSettings, "script.inline"));
}
private static class CustomScriptEngine implements ScriptEngine {
public static final String NAME = "custom";
@Override
public String getType() {
return NAME;
}
@Override
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
return null;
}
@Override
public ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars) {
return null;
}
@Override
public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, @Nullable Map<String, Object> vars) {
return null;
}
@Override
public void close() {
}
}
}

View File

@ -28,7 +28,6 @@ import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContextRegistry; import org.elasticsearch.script.ScriptContextRegistry;
import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptSettings;
import org.elasticsearch.script.ScriptType; import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.test.InternalAggregationTestCase; import org.elasticsearch.test.InternalAggregationTestCase;
@ -75,10 +74,8 @@ public class InternalScriptedMetricTests extends InternalAggregationTestCase<Int
})); }));
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(scriptEngine)); ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(scriptEngine));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
try { try {
return new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry, return new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry);
scriptSettings);
} catch (IOException e) { } catch (IOException e) {
throw new ElasticsearchException(e); throw new ElasticsearchException(e);
} }

View File

@ -38,7 +38,6 @@ import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContextRegistry; import org.elasticsearch.script.ScriptContextRegistry;
import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptSettings;
import org.elasticsearch.script.ScriptType; import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.aggregations.AggregatorTestCase; import org.elasticsearch.search.aggregations.AggregatorTestCase;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -201,10 +200,9 @@ public class ScriptedMetricAggregatorTests extends AggregatorTestCase {
MockScriptEngine scriptEngine = new MockScriptEngine(MockScriptEngine.NAME, SCRIPTS); MockScriptEngine scriptEngine = new MockScriptEngine(MockScriptEngine.NAME, SCRIPTS);
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(scriptEngine)); ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(scriptEngine));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
ScriptService scriptService; ScriptService scriptService;
try { try {
scriptService = new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry, scriptSettings); scriptService = new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry);
} catch (IOException e) { } catch (IOException e) {
throw new ElasticsearchException(e); throw new ElasticsearchException(e);
} }

View File

@ -57,7 +57,6 @@ import org.elasticsearch.script.ScriptContextRegistry;
import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptServiceTests.TestEngine; import org.elasticsearch.script.ScriptServiceTests.TestEngine;
import org.elasticsearch.script.ScriptSettings;
import org.elasticsearch.script.ScriptType; import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.SearchModule; import org.elasticsearch.search.SearchModule;
@ -89,11 +88,9 @@ public abstract class AbstractSortTestCase<T extends SortBuilder<T>> extends EST
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
.put(Environment.PATH_CONF_SETTING.getKey(), genericConfigFolder) .put(Environment.PATH_CONF_SETTING.getKey(), genericConfigFolder)
.build(); .build();
Environment environment = new Environment(baseSettings);
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new TestEngine())); ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new TestEngine()));
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); scriptService = new ScriptService(baseSettings, scriptEngineRegistry, scriptContextRegistry) {
scriptService = new ScriptService(baseSettings, scriptEngineRegistry, scriptContextRegistry, scriptSettings) {
@Override @Override
public CompiledScript compile(Script script, ScriptContext scriptContext) { public CompiledScript compile(Script script, ScriptContext scriptContext) {
return new CompiledScript(ScriptType.INLINE, "mockName", "test", script); return new CompiledScript(ScriptType.INLINE, "mockName", "test", script);

View File

@ -200,7 +200,7 @@ def smoke_test_release(release, files, hash, plugins):
headers = {} headers = {}
print(' Starting elasticsearch deamon from [%s]' % es_dir) print(' Starting elasticsearch deamon from [%s]' % es_dir)
try: try:
run('%s; %s -Enode.name=smoke_tester -Ecluster.name=prepare_release -Escript.inline=true -Escript.stored=true -Erepositories.url.allowed_urls=http://snapshot.test* %s -Epidfile=%s -Enode.portsfile=true' run('%s; %s -Enode.name=smoke_tester -Ecluster.name=prepare_release -Erepositories.url.allowed_urls=http://snapshot.test* %s -Epidfile=%s -Enode.portsfile=true'
% (java_exe(), es_run_path, '-d', os.path.join(es_dir, 'es-smoke.pid'))) % (java_exe(), es_run_path, '-d', os.path.join(es_dir, 'es-smoke.pid')))
if not wait_for_node_startup(es_dir, header=headers): if not wait_for_node_startup(es_dir, header=headers):
print("elasticsearch logs:") print("elasticsearch logs:")

View File

@ -57,8 +57,6 @@ buildRestTests.expectedUnconvertedCandidates = [
] ]
integTestCluster { integTestCluster {
setting 'script.inline', 'true'
setting 'script.stored', 'true'
setting 'script.max_compilations_per_minute', '1000' setting 'script.max_compilations_per_minute', '1000'
/* Enable regexes in painless so our tests don't complain about example /* Enable regexes in painless so our tests don't complain about example
* snippets that use them. */ * snippets that use them. */

View File

@ -24,5 +24,5 @@ The `_index` variable has been removed. If you used it for advanced scoring, con
==== Script Settings ==== Script Settings
All of the existing scripting security settings have been deprecated. Instead All of the existing scripting security settings have been removed. Instead
they are replaced with `script.allowed_types` and `script.allowed_contexts`. they are replaced with `script.allowed_types` and `script.allowed_contexts`.

View File

@ -74,5 +74,5 @@ deprecation warning.
==== Script Settings ==== Script Settings
All of the existing scripting security settings have been deprecated. Instead All of the existing scripting security settings have been removed. Instead
they are replaced with `script.allowed_types` and `script.allowed_contexts`. they are replaced with `script.allowed_types` and `script.allowed_contexts`.

View File

@ -93,7 +93,8 @@ security of the Elasticsearch deployment.
By default all script types are allowed to be executed. This can be modified using the By default all script types are allowed to be executed. This can be modified using the
setting `script.allowed_types`. Only the types specified as part of the setting will be setting `script.allowed_types`. Only the types specified as part of the setting will be
allowed to be executed. allowed to be executed. To specify no types are allowed, set `scripts.allowed_types` to
be `none`.
[source,yaml] [source,yaml]
---- ----
@ -108,7 +109,8 @@ script.allowed_types: inline <1>
By default all script contexts are allowed to be executed. This can be modified using the By default all script contexts are allowed to be executed. This can be modified using the
setting `script.allowed_contexts`. Only the contexts specified as part of the setting will setting `script.allowed_contexts`. Only the contexts specified as part of the setting will
be allowed to be executed. be allowed to be executed. To specify no contexts are allowed, set `scripts.allowed_contexts`
to be `none`.
[source,yaml] [source,yaml]
---- ----
@ -116,105 +118,3 @@ script.allowed_contexts: search, update <1>
---- ----
<1> This will allow only search and update scripts to be executed but not <1> This will allow only search and update scripts to be executed but not
aggs or plugin scripts (or any other contexts). aggs or plugin scripts (or any other contexts).
[[deprecated-script=settings]]
[float]
=== Deprecated script settings
The following settings have all been deprecated and will be removed in 6.0:
* <<security-script-source>>
* <<security-script-context>>
* <<security-script-fine>>
Use the following instead:
* <<allowed-script-types-setting>>
* <<allowed-script-contexts-setting>>
[[security-script-source]]
[float]
=== Script source settings
Which scripts Elasticsearch will execute where is controlled by settings
starting with `scripts.`. The simplest settings allow scripts to be enabled
or disabled based on where they are stored. For example:
[source,yaml]
-----------------------------------
script.inline: false <1>
script.stored: false <2>
-----------------------------------
<1> Refuse to run scripts provided inline in the API.
<2> Refuse to run scripts stored using the API.
NOTE: These settings override the defaults mentioned
<<modules-scripting-security-do-no-weaken, above>>. Recreating the defaults
requires more fine grained settings described <<security-script-fine, below>>.
[[security-script-context]]
[float]
=== Script context settings
Scripting may also be enabled or disabled in different contexts in the
Elasticsearch API. The supported contexts are:
[horizontal]
`aggs`:: Aggregations
`search`:: Search api, Percolator API and Suggester API
`update`:: Update api
`plugin`:: Any plugin that makes use of scripts under the generic `plugin` category
Plugins can also define custom operations that they use scripts for instead
of using the generic `plugin` category. Those operations can be referred to
in the following form: `${pluginName}_${operation}`.
The following example disables scripting for `update` and `plugin` operations,
regardless of the script source or language. Scripts can still be executed
as part of `aggregations`, `search` and plugins execution though, as the above
defaults still get applied.
[source,yaml]
-----------------------------------
script.update: false
script.plugin: false
-----------------------------------
[[security-script-fine]]
[float]
=== Fine-grained script settings
First, the high-level script settings described above are applied in order
(context settings have precedence over source settings). Then fine-grained
settings which include the script language take precedence over any high-level
settings. They have two forms:
[source,yaml]
------------------------
script.engine.{lang}.{inline|stored}.{context}: true|false
------------------------
And
[source,yaml]
------------------------
script.engine.{lang}.{inline|stored}: true|false
------------------------
For example:
[source,yaml]
-----------------------------------
script.inline: false <1>
script.stored: false <1>
script.engine.painless.inline: true <2>
script.engine.painless.stored.search: true <3>
script.engine.painless.stored.aggs: true <3>
script.engine.mustache.stored.search: true <4>
-----------------------------------
<1> Disable all scripting from any source.
<2> Allow inline Painless scripts for all operations.
<3> Allow stored Painless scripts to be used for search and aggregations.
<4> Allow stored Mustache templates to be used for search.

View File

@ -40,8 +40,7 @@ public class StoredExpressionTests extends ESIntegTestCase {
@Override @Override
protected Settings nodeSettings(int nodeOrdinal) { protected Settings nodeSettings(int nodeOrdinal) {
Settings.Builder builder = Settings.builder().put(super.nodeSettings(nodeOrdinal)); Settings.Builder builder = Settings.builder().put(super.nodeSettings(nodeOrdinal));
builder.put("script.engine.expression.stored.update", "false"); builder.put("script.contexts_allowed", "update");
builder.put("script.engine.expression.stored.search", "false");
return builder.build(); return builder.build();
} }
@ -72,7 +71,7 @@ public class StoredExpressionTests extends ESIntegTestCase {
.setIndices("test").setTypes("scriptTest").get(); .setIndices("test").setTypes("scriptTest").get();
fail("search script should have been rejected"); fail("search script should have been rejected");
} catch(Exception e) { } catch(Exception e) {
assertThat(e.toString(), containsString("scripts of type [stored], operation [search] and lang [expression] are disabled")); assertThat(e.toString(), containsString("cannot execute scripts using [search] context"));
} }
try { try {
client().prepareSearch("test") client().prepareSearch("test")
@ -80,7 +79,7 @@ public class StoredExpressionTests extends ESIntegTestCase {
new SearchSourceBuilder().aggregation(AggregationBuilders.terms("test").script( new SearchSourceBuilder().aggregation(AggregationBuilders.terms("test").script(
new Script(ScriptType.STORED, "expression", "script1", Collections.emptyMap())))).get(); new Script(ScriptType.STORED, "expression", "script1", Collections.emptyMap())))).get();
} catch (Exception e) { } catch (Exception e) {
assertThat(e.toString(), containsString("scripts of type [stored], operation [aggs] and lang [expression] are disabled")); assertThat(e.toString(), containsString("cannot execute scripts using [aggs] context"));
} }
} }
} }

View File

@ -28,7 +28,5 @@ dependencies {
} }
integTestCluster { integTestCluster {
setting 'script.inline', 'true'
setting 'script.stored', 'true'
setting 'script.max_compilations_per_minute', '1000' setting 'script.max_compilations_per_minute', '1000'
} }

View File

@ -45,5 +45,4 @@ thirdPartyAudit.excludes = [
integTestCluster { integTestCluster {
setting 'cloud.azure.storage.my_account_test.account', 'cloudazureresource' setting 'cloud.azure.storage.my_account_test.account', 'cloudazureresource'
setting 'cloud.azure.storage.my_account_test.key', 'abcdefgh' setting 'cloud.azure.storage.my_account_test.key', 'abcdefgh'
setting 'script.stored', 'true'
} }

View File

@ -30,6 +30,5 @@ dependencies {
integTestCluster { integTestCluster {
plugin ':plugins:ingest-geoip' plugin ':plugins:ingest-geoip'
setting 'script.inline', 'true'
setting 'script.max_compilations_per_minute', '1000' setting 'script.max_compilations_per_minute', '1000'
} }

View File

@ -19,30 +19,25 @@
package org.elasticsearch.ingest; package org.elasticsearch.ingest;
import java.util.Arrays;
import java.util.Collections;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.script.ScriptContextRegistry; import org.elasticsearch.script.ScriptContextRegistry;
import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptSettings;
import org.elasticsearch.script.mustache.MustacheScriptEngine; import org.elasticsearch.script.mustache.MustacheScriptEngine;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.junit.Before; import org.junit.Before;
import java.util.Collections;
public abstract class AbstractScriptTestCase extends ESTestCase { public abstract class AbstractScriptTestCase extends ESTestCase {
protected TemplateService templateService; protected TemplateService templateService;
@Before @Before
public void init() throws Exception { public void init() throws Exception {
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Arrays.asList(new MustacheScriptEngine())); ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new MustacheScriptEngine()));
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); ScriptService scriptService = new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry);
ScriptService scriptService = new ScriptService(Settings.EMPTY, scriptEngineRegistry, scriptContextRegistry, scriptSettings);
templateService = new InternalTemplateService(scriptService); templateService = new InternalTemplateService(scriptService);
} }

View File

@ -1013,10 +1013,9 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
new Class[]{Client.class}, new Class[]{Client.class},
clientInvocationHandler); clientInvocationHandler);
ScriptModule scriptModule = createScriptModule(pluginsService.filterPlugins(ScriptPlugin.class)); ScriptModule scriptModule = createScriptModule(pluginsService.filterPlugins(ScriptPlugin.class));
List<Setting<?>> scriptSettings = scriptModule.getSettings(); List<Setting<?>> additionalSettings = pluginsService.getPluginSettings();
scriptSettings.addAll(pluginsService.getPluginSettings()); additionalSettings.add(InternalSettingsPlugin.VERSION_CREATED);
scriptSettings.add(InternalSettingsPlugin.VERSION_CREATED); SettingsModule settingsModule = new SettingsModule(nodeSettings, additionalSettings, pluginsService.getPluginSettingsFilter());
SettingsModule settingsModule = new SettingsModule(nodeSettings, scriptSettings, pluginsService.getPluginSettingsFilter());
searchModule = new SearchModule(nodeSettings, false, pluginsService.filterPlugins(SearchPlugin.class)); searchModule = new SearchModule(nodeSettings, false, pluginsService.filterPlugins(SearchPlugin.class));
IndicesModule indicesModule = new IndicesModule(pluginsService.filterPlugins(MapperPlugin.class)); IndicesModule indicesModule = new IndicesModule(pluginsService.filterPlugins(MapperPlugin.class));
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>(); List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();

View File

@ -1722,8 +1722,6 @@ public abstract class ESIntegTestCase extends ESTestCase {
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b") .put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b")
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b") .put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b")
.put(ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE.getKey(), 1000) .put(ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE.getKey(), 1000)
.put("script.stored", "true")
.put("script.inline", "true")
// by default we never cache below 10k docs in a segment, // by default we never cache below 10k docs in a segment,
// bypass this limit so that caching gets some testing in // bypass this limit so that caching gets some testing in
// integration tests that usually create few documents // integration tests that usually create few documents