mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-23 21:38:15 +00:00
Add a soft limit on the mapping depth. #17400
This commit adds the new `index.mapping.depth.limit` setting which controls the maximum mapping depth that is allowed. It has a default value of 20.
This commit is contained in:
parent
068c788ec8
commit
fc47007e17
@ -129,6 +129,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings {
|
||||
MapperService.INDEX_MAPPER_DYNAMIC_SETTING,
|
||||
MapperService.INDEX_MAPPING_NESTED_FIELDS_LIMIT_SETTING,
|
||||
MapperService.INDEX_MAPPING_TOTAL_FIELDS_LIMIT_SETTING,
|
||||
MapperService.INDEX_MAPPING_DEPTH_LIMIT_SETTING,
|
||||
BitsetFilterCache.INDEX_LOAD_RANDOM_ACCESS_FILTERS_EAGERLY_SETTING,
|
||||
IndexModule.INDEX_STORE_TYPE_SETTING,
|
||||
IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING,
|
||||
|
@ -86,6 +86,8 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
|
||||
Setting.longSetting("index.mapping.nested_fields.limit", 50L, 0, Property.Dynamic, Property.IndexScope);
|
||||
public static final Setting<Long> INDEX_MAPPING_TOTAL_FIELDS_LIMIT_SETTING =
|
||||
Setting.longSetting("index.mapping.total_fields.limit", 1000L, 0, Property.Dynamic, Property.IndexScope);
|
||||
public static final Setting<Long> INDEX_MAPPING_DEPTH_LIMIT_SETTING =
|
||||
Setting.longSetting("index.mapping.depth.limit", 20L, 1, Property.Dynamic, Property.IndexScope);
|
||||
public static final boolean INDEX_MAPPER_DYNAMIC_DEFAULT = true;
|
||||
public static final Setting<Boolean> INDEX_MAPPER_DYNAMIC_SETTING =
|
||||
Setting.boolSetting("index.mapper.dynamic", INDEX_MAPPER_DYNAMIC_DEFAULT, Property.IndexScope);
|
||||
@ -292,6 +294,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
|
||||
// this check will be skipped.
|
||||
checkNestedFieldsLimit(fullPathObjectMappers);
|
||||
checkTotalFieldsLimit(objectMappers.size() + fieldMappers.size());
|
||||
checkDepthLimit(fullPathObjectMappers.keySet());
|
||||
}
|
||||
|
||||
Set<String> parentTypes = this.parentTypes;
|
||||
@ -418,6 +421,27 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDepthLimit(Collection<String> objectPaths) {
|
||||
final long maxDepth = indexSettings.getValue(INDEX_MAPPING_DEPTH_LIMIT_SETTING);
|
||||
for (String objectPath : objectPaths) {
|
||||
checkDepthLimit(objectPath, maxDepth);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDepthLimit(String objectPath, long maxDepth) {
|
||||
int numDots = 0;
|
||||
for (int i = 0; i < objectPath.length(); ++i) {
|
||||
if (objectPath.charAt(i) == '.') {
|
||||
numDots += 1;
|
||||
}
|
||||
}
|
||||
final int depth = numDots + 2;
|
||||
if (depth > maxDepth) {
|
||||
throw new IllegalArgumentException("Limit of mapping depth [" + maxDepth + "] in index [" + index().getName()
|
||||
+ "] has been exceeded due to object field [" + objectPath + "]");
|
||||
}
|
||||
}
|
||||
|
||||
public DocumentMapper parse(String mappingType, CompressedXContent mappingSource, boolean applyDefault) throws MapperParsingException {
|
||||
String defaultMappingSource;
|
||||
if (PercolatorFieldMapper.TYPE_NAME.equals(mappingType)) {
|
||||
|
@ -161,4 +161,31 @@ public class MapperServiceTests extends ESSingleNodeTestCase {
|
||||
assertThat(e.getMessage(), containsString("Limit of total fields [1] in index [test2] has been exceeded"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testMappingDepthExceedsLimit() throws Throwable {
|
||||
CompressedXContent simpleMapping = new CompressedXContent(XContentFactory.jsonBuilder().startObject()
|
||||
.startObject("properties")
|
||||
.startObject("field")
|
||||
.field("type", "text")
|
||||
.endObject()
|
||||
.endObject().endObject().bytes());
|
||||
IndexService indexService1 = createIndex("test1", Settings.builder().put(MapperService.INDEX_MAPPING_DEPTH_LIMIT_SETTING.getKey(), 1).build());
|
||||
// no exception
|
||||
indexService1.mapperService().merge("type", simpleMapping, MergeReason.MAPPING_UPDATE, false);
|
||||
|
||||
CompressedXContent objectMapping = new CompressedXContent(XContentFactory.jsonBuilder().startObject()
|
||||
.startObject("properties")
|
||||
.startObject("object1")
|
||||
.field("type", "object")
|
||||
.endObject()
|
||||
.endObject().endObject().bytes());
|
||||
|
||||
IndexService indexService2 = createIndex("test2");
|
||||
// no exception
|
||||
indexService2.mapperService().merge("type", objectMapping, MergeReason.MAPPING_UPDATE, false);
|
||||
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||
() -> indexService1.mapperService().merge("type2", objectMapping, MergeReason.MAPPING_UPDATE, false));
|
||||
assertThat(e.getMessage(), containsString("Limit of mapping depth [1] in index [test1] has been exceeded"));
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,19 @@ detected. All other datatypes must be mapped explicitly.
|
||||
Besides the options listed below, dynamic field mapping rules can be further
|
||||
customised with <<dynamic-templates,`dynamic_templates`>>.
|
||||
|
||||
[[total-fields-limit]]
|
||||
==== Total fields limit
|
||||
[[mapping-limit-settings]]
|
||||
==== Settings to prevent mappings explosion
|
||||
|
||||
To avoid mapping explosion, Index has a default limit of 1000 total number of fields.
|
||||
The default setting can be updated with `index.mapping.total_fields.limit`.
|
||||
Two settings allow to control mapping explosion, in order to prevent adversary
|
||||
documents to create huge mappings through dynamic mappings for instance:
|
||||
|
||||
`index.mapping.total_fields.limit`::
|
||||
The maximum number of fields in an index. The default value is `1000`.
|
||||
`index.mapping.depth.limit`::
|
||||
The maximum depth for a field, which is measured as the number of nested
|
||||
objects. For instance, if all fields are defined at the root object level,
|
||||
then the depth is `1`. If there is one object mapping, then the depth is
|
||||
`2`, etc. The default is `20`.
|
||||
|
||||
[[date-detection]]
|
||||
==== Date detection
|
||||
|
Loading…
x
Reference in New Issue
Block a user