Skip to content

Commit

Permalink
Scripting: remove support for script.disable_dynamic setting
Browse files Browse the repository at this point in the history
Now that fine-grained script settings are supported (elastic#10116) we can remove support for the script.disable_dynamic setting.

Same result as `script.disable_dynamic: false` can be obtained as follows:

```
script.inline: on
script.indexed: on
```
An exception is thrown at startup when the old setting is set, so we make sure we tell users they have to change it rather than ignoring the setting.

Closes elastic#10286
  • Loading branch information
javanna committed Mar 31, 2015
1 parent 7a595d7 commit 83fb0a1
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 249 deletions.
22 changes: 21 additions & 1 deletion docs/reference/migration/migrate_2_0.asciidoc
Expand Up @@ -286,7 +286,27 @@ setting. Please however note that using a non-default codec is discouraged as
it could prevent future versions of Elasticsearch from being able to read the
index.

=== Scripts
=== Scripting settings

Removed support for `script.disable_dynamic` node setting, replaced by
fine-grained script settings described in the <<enable-dynamic-scripting,scripting docs>>.
The following setting previously used to enable dynamic scripts:

[source,yaml]
---------------
script.disable_dynamic: false
---------------

can be replaced with the following two settings in `elasticsearch.yml` that
achieve the same result:

[source,yaml]
---------------
script.inline: on
script.indexed: on
---------------

=== Script parameters

Deprecated script parameters `id`, `file`, and `scriptField` have been removed
from all scriptable APIs. `script_id`, `script_file` and `script` should be used
Expand Down
2 changes: 0 additions & 2 deletions docs/reference/modules/scripting.asciidoc
Expand Up @@ -246,8 +246,6 @@ application inbetween. If you *do* intend to expose Elasticsearch directly to
your users, then you have to decide whether you trust them enough to run scripts
on your box or not.

deprecated[1.6.0, the `script.disable_dynamic` setting is deprecated in favour of fine-grained settings described as follows]

It is possible to enable scripts based on their source, for
every script engine, through the following settings that need to be added to the
`config/elasticsearch.yml` file on every node.
Expand Down
56 changes: 13 additions & 43 deletions src/main/java/org/elasticsearch/script/ScriptModes.java
Expand Up @@ -20,15 +20,16 @@
package org.elasticsearch.script;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.ScriptService.ScriptType;

import java.util.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
* Holds the {@link org.elasticsearch.script.ScriptMode}s for each of the different scripting languages available,
Expand All @@ -41,15 +42,15 @@ public class ScriptModes {

final ImmutableMap<String, ScriptMode> scriptModes;

ScriptModes(Map<String, ScriptEngineService> scriptEngines, Settings settings, ESLogger logger) {
ScriptModes(Map<String, ScriptEngineService> scriptEngines, Settings settings) {
//filter out the native engine as we don't want to apply fine grained settings to it.
//native scripts are always on as they are static by definition.
Map<String, ScriptEngineService> filteredEngines = Maps.newHashMap(scriptEngines);
filteredEngines.remove(NativeScriptEngineService.NAME);
this.scriptModes = buildScriptModeSettingsMap(settings, filteredEngines, logger);
this.scriptModes = buildScriptModeSettingsMap(settings, filteredEngines);
}

private ImmutableMap<String, ScriptMode> buildScriptModeSettingsMap(Settings settings, Map<String, ScriptEngineService> scriptEngines, ESLogger logger) {
private ImmutableMap<String, ScriptMode> buildScriptModeSettingsMap(Settings settings, Map<String, ScriptEngineService> scriptEngines) {
HashMap<String, ScriptMode> scriptModesMap = Maps.newHashMap();

//file scripts are enabled by default, for any language
Expand All @@ -59,39 +60,35 @@ private ImmutableMap<String, ScriptMode> buildScriptModeSettingsMap(Settings set
//dynamic scripts are enabled by default only for sandboxed languages
addGlobalScriptTypeModes(scriptEngines.keySet(), ScriptType.INLINE, ScriptMode.SANDBOX, scriptModesMap);

List<String> processedSettings = Lists.newArrayList();
processSourceBasedGlobalSettings(settings, scriptEngines, processedSettings, scriptModesMap);
processOperationBasedGlobalSettings(settings, scriptEngines, processedSettings, scriptModesMap);
processEngineSpecificSettings(settings, scriptEngines, processedSettings, scriptModesMap);
processDisableDynamicDeprecatedSetting(settings, scriptEngines, processedSettings, scriptModesMap, logger);
processSourceBasedGlobalSettings(settings, scriptEngines, scriptModesMap);
processOperationBasedGlobalSettings(settings, scriptEngines, scriptModesMap);
processEngineSpecificSettings(settings, scriptEngines, scriptModesMap);
return ImmutableMap.copyOf(scriptModesMap);
}

private static void processSourceBasedGlobalSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, List<String> processedSettings, Map<String, ScriptMode> scriptModes) {
private static void processSourceBasedGlobalSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, Map<String, ScriptMode> scriptModes) {
//read custom source based settings for all operations (e.g. script.indexed: on)
for (ScriptType scriptType : ScriptType.values()) {
String scriptTypeSetting = settings.get(SCRIPT_SETTINGS_PREFIX + scriptType);
if (Strings.hasLength(scriptTypeSetting)) {
ScriptMode scriptTypeMode = ScriptMode.parse(scriptTypeSetting);
processedSettings.add(SCRIPT_SETTINGS_PREFIX + scriptType + ": " + scriptTypeMode);
addGlobalScriptTypeModes(scriptEngines.keySet(), scriptType, scriptTypeMode, scriptModes);
}
}
}

private static void processOperationBasedGlobalSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, List<String> processedSettings, Map<String, ScriptMode> scriptModes) {
private static void processOperationBasedGlobalSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, Map<String, ScriptMode> scriptModes) {
//read custom op based settings for all sources (e.g. script.aggs: off)
//op based settings take precedence over source based settings, hence they get expanded later
for (ScriptContext scriptContext : ScriptContext.values()) {
ScriptMode scriptMode = getScriptContextMode(settings, SCRIPT_SETTINGS_PREFIX, scriptContext);
if (scriptMode != null) {
processedSettings.add(SCRIPT_SETTINGS_PREFIX + scriptContext + ": " + scriptMode);
addGlobalScriptContextModes(scriptEngines.keySet(), scriptContext, scriptMode, scriptModes);
}
}
}

private static void processEngineSpecificSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, List<String> processedSettings, Map<String, ScriptMode> scriptModes) {
private static void processEngineSpecificSettings(Settings settings, Map<String, ScriptEngineService> scriptEngines, Map<String, ScriptMode> scriptModes) {
Map<String, Settings> langGroupedSettings = settings.getGroups(ENGINE_SETTINGS_PREFIX, true);
for (Map.Entry<String, Settings> langSettings : langGroupedSettings.entrySet()) {
//read engine specific settings that refer to a non existing script lang will be ignored
Expand All @@ -103,7 +100,6 @@ private static void processEngineSpecificSettings(Settings settings, Map<String,
for (ScriptContext scriptContext : ScriptContext.values()) {
ScriptMode scriptMode = getScriptContextMode(langSettings.getValue(), scriptTypePrefix, scriptContext);
if (scriptMode != null) {
processedSettings.add(enginePrefix + scriptTypePrefix + scriptContext + ": " + scriptMode);
addScriptMode(scriptEngineService, scriptType, scriptContext, scriptMode, scriptModes);
}
}
Expand All @@ -112,32 +108,6 @@ private static void processEngineSpecificSettings(Settings settings, Map<String,
}
}

private void processDisableDynamicDeprecatedSetting(Settings settings, Map<String, ScriptEngineService> scriptEngines,
List<String> processedSettings, Map<String, ScriptMode> scriptModes, ESLogger logger) {
//read deprecated disable_dynamic setting, apply only if none of the new settings is used
String disableDynamicSetting = settings.get(ScriptService.DISABLE_DYNAMIC_SCRIPTING_SETTING);
if (disableDynamicSetting != null) {
if (processedSettings.isEmpty()) {
ScriptService.DynamicScriptDisabling dynamicScriptDisabling = ScriptService.DynamicScriptDisabling.parse(disableDynamicSetting);
switch(dynamicScriptDisabling) {
case EVERYTHING_ALLOWED:
addGlobalScriptTypeModes(scriptEngines.keySet(), ScriptType.INDEXED, ScriptMode.ON, scriptModes);
addGlobalScriptTypeModes(scriptEngines.keySet(), ScriptType.INLINE, ScriptMode.ON, scriptModes);
break;
case ONLY_DISK_ALLOWED:
addGlobalScriptTypeModes(scriptEngines.keySet(), ScriptType.INDEXED, ScriptMode.OFF, scriptModes);
addGlobalScriptTypeModes(scriptEngines.keySet(), ScriptType.INLINE, ScriptMode.OFF, scriptModes);
break;
}
logger.warn("deprecated setting [{}] is set, replace with fine-grained scripting settings (e.g. script.inline, script.indexed, script.file)", ScriptService.DISABLE_DYNAMIC_SCRIPTING_SETTING);
} else {
processedSettings.add(ScriptService.DISABLE_DYNAMIC_SCRIPTING_SETTING + ": " + disableDynamicSetting);
throw new ElasticsearchIllegalArgumentException("conflicting scripting settings have been specified, use either "
+ ScriptService.DISABLE_DYNAMIC_SCRIPTING_SETTING + " (deprecated) or the newer fine-grained settings (e.g. script.inline, script.indexed, script.file), not both at the same time:\n" + processedSettings);
}
}
}

private static ScriptMode getScriptContextMode(Settings settings, String prefix, ScriptContext scriptContext) {
String settingValue = settings.get(prefix + scriptContext);
if (Strings.hasLength(settingValue)) {
Expand Down
41 changes: 8 additions & 33 deletions src/main/java/org/elasticsearch/script/ScriptService.java
Expand Up @@ -81,8 +81,9 @@
*/
public class ScriptService extends AbstractComponent implements Closeable {

static final String DISABLE_DYNAMIC_SCRIPTING_SETTING = "script.disable_dynamic";

public static final String DEFAULT_SCRIPTING_LANGUAGE_SETTING = "script.default_lang";
public static final String DISABLE_DYNAMIC_SCRIPTING_SETTING = "script.disable_dynamic";
public static final String SCRIPT_CACHE_SIZE_SETTING = "script.cache.max_size";
public static final String SCRIPT_CACHE_EXPIRE_SETTING = "script.cache.expire";
public static final String SCRIPT_INDEX = ".scripts";
Expand All @@ -105,37 +106,6 @@ public class ScriptService extends AbstractComponent implements Closeable {

private Client client = null;

/**
* Enum defining the different dynamic settings for scripting, either
* ONLY_DISK_ALLOWED (scripts must be placed on disk), EVERYTHING_ALLOWED
* (all dynamic scripting is enabled), or SANDBOXED_ONLY (only sandboxed
* scripting languages are allowed)
*/
enum DynamicScriptDisabling {
EVERYTHING_ALLOWED,
ONLY_DISK_ALLOWED,
SANDBOXED_ONLY;

static DynamicScriptDisabling parse(String s) {
switch (s.toLowerCase(Locale.ROOT)) {
// true for "disable_dynamic" means only on-disk scripts are enabled
case "true":
case "all":
return ONLY_DISK_ALLOWED;
// false for "disable_dynamic" means all scripts are enabled
case "false":
case "none":
return EVERYTHING_ALLOWED;
// only sandboxed scripting is enabled
case "sandbox":
case "sandboxed":
return SANDBOXED_ONLY;
default:
throw new ElasticsearchIllegalArgumentException("Unrecognized script allowance setting: [" + s + "]");
}
}
}

public static final ParseField SCRIPT_LANG = new ParseField("lang","script_lang");
public static final ParseField SCRIPT_FILE = new ParseField("script_file");
public static final ParseField SCRIPT_ID = new ParseField("script_id");
Expand All @@ -146,6 +116,11 @@ public ScriptService(Settings settings, Environment env, Set<ScriptEngineService
ResourceWatcherService resourceWatcherService, NodeSettingsService nodeSettingsService) throws IOException {
super(settings);

if (Strings.hasLength(settings.get(DISABLE_DYNAMIC_SCRIPTING_SETTING))) {
throw new ElasticsearchIllegalArgumentException(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: on` and `script.indexed: on` in elasticsearch.yml");
}

this.scriptEngines = scriptEngines;
int cacheMaxSize = settings.getAsInt(SCRIPT_CACHE_SIZE_SETTING, 100);
TimeValue cacheExpire = settings.getAsTime(SCRIPT_CACHE_EXPIRE_SETTING, null);
Expand Down Expand Up @@ -175,7 +150,7 @@ public ScriptService(Settings settings, Environment env, Set<ScriptEngineService
this.scriptEnginesByLang = enginesByLangBuilder.build();
this.scriptEnginesByExt = enginesByExtBuilder.build();

this.scriptModes = new ScriptModes(this.scriptEnginesByLang, settings, logger);
this.scriptModes = new ScriptModes(this.scriptEnginesByLang, settings);

// add file watcher for static scripts
scriptsDirectory = env.configFile().resolve("scripts");
Expand Down
3 changes: 0 additions & 3 deletions src/test/java/org/elasticsearch/env/NodeEnvironmentTests.java
Expand Up @@ -27,7 +27,6 @@
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.junit.Test;

Expand Down Expand Up @@ -399,7 +398,6 @@ public NodeEnvironment newNodeEnvironment(Settings settings) throws IOException
.put(settings)
.put("path.home", newTempDirPath().toAbsolutePath().toString())
.put(NodeEnvironment.SETTING_CUSTOM_DATA_PATH_ENABLED, true)
.put(ScriptService.DISABLE_DYNAMIC_SCRIPTING_SETTING, false)
.putArray("path.data", tmpPaths()).build();
return new NodeEnvironment(build, new Environment(build));
}
Expand All @@ -409,7 +407,6 @@ public NodeEnvironment newNodeEnvironment(String[] dataPaths, Settings settings)
.put(settings)
.put("path.home", newTempDirPath().toAbsolutePath().toString())
.put(NodeEnvironment.SETTING_CUSTOM_DATA_PATH_ENABLED, true)
.put(ScriptService.DISABLE_DYNAMIC_SCRIPTING_SETTING, false)
.putArray("path.data", dataPaths).build();
return new NodeEnvironment(build, new Environment(build));
}
Expand Down
15 changes: 0 additions & 15 deletions src/test/java/org/elasticsearch/script/NativeScriptTests.java
Expand Up @@ -86,21 +86,6 @@ public void testFineGrainedSettingsDontAffectNativeScripts() throws IOException
}
}

@Test
public void testDisableDynamicDoesntAffectNativeScripts() throws IOException {
Settings settings = ImmutableSettings.settingsBuilder().put(ScriptService.DISABLE_DYNAMIC_SCRIPTING_SETTING, randomFrom("true", "false", "sandbox")).build();
Environment environment = new Environment(settings);
ResourceWatcherService resourceWatcherService = new ResourceWatcherService(settings, null);
Map<String, NativeScriptFactory> nativeScriptFactoryMap = new HashMap<>();
nativeScriptFactoryMap.put("my", new MyNativeScriptFactory());
Set<ScriptEngineService> scriptEngineServices = ImmutableSet.<ScriptEngineService>of(new NativeScriptEngineService(settings, nativeScriptFactoryMap));
ScriptService scriptService = new ScriptService(settings, environment, scriptEngineServices, resourceWatcherService, new NodeSettingsService(settings));

for (ScriptContext scriptContext : ScriptContext.values()) {
assertThat(scriptService.compile(NativeScriptEngineService.NAME, "my", ScriptType.INLINE, scriptContext), notNullValue());
}
}

static class MyNativeScriptFactory implements NativeScriptFactory {
@Override
public ExecutableScript newScript(@Nullable Map<String, Object> params) {
Expand Down

0 comments on commit 83fb0a1

Please sign in to comment.