Validate top-level keys for create index request (#23755) (#23869)

This commit ensures create index requests do not ignore unknown keys passed to the request.

closes #23755
This commit is contained in:
olcbean 2017-09-26 18:49:20 +02:00 committed by Ryan Ernst
parent 5df77a8c91
commit 6952f7b560
6 changed files with 63 additions and 33 deletions

View File

@ -374,38 +374,32 @@ public class CreateIndexRequest extends AcknowledgedRequest<CreateIndexRequest>
*/
@SuppressWarnings("unchecked")
public CreateIndexRequest source(Map<String, ?> source) {
boolean found = false;
for (Map.Entry<String, ?> entry : source.entrySet()) {
String name = entry.getKey();
if (name.equals("settings")) {
found = true;
settings((Map<String, Object>) entry.getValue());
} else if (name.equals("mappings")) {
found = true;
Map<String, Object> mappings = (Map<String, Object>) entry.getValue();
for (Map.Entry<String, Object> entry1 : mappings.entrySet()) {
mapping(entry1.getKey(), (Map<String, Object>) entry1.getValue());
}
} else if (name.equals("aliases")) {
found = true;
aliases((Map<String, Object>) entry.getValue());
} else {
// maybe custom?
IndexMetaData.Custom proto = IndexMetaData.lookupPrototype(name);
if (proto != null) {
found = true;
try {
customs.put(name, proto.fromMap((Map<String, Object>) entry.getValue()));
} catch (IOException e) {
throw new ElasticsearchParseException("failed to parse custom metadata for [{}]", name);
}
} else {
// found a key which is neither custom defined nor one of the supported ones
throw new ElasticsearchParseException("unknown key [{}] for create index", name);
}
}
}
if (!found) {
// the top level are settings, use them
settings(source);
}
return this;
}

View File

@ -19,6 +19,7 @@
package org.elasticsearch.action.admin.indices.create;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
@ -31,6 +32,7 @@ import org.junit.Before;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class CreateIndexRequestBuilderTests extends ESTestCase {
@ -58,16 +60,23 @@ public class CreateIndexRequestBuilderTests extends ESTestCase {
*/
public void testSetSource() throws IOException {
CreateIndexRequestBuilder builder = new CreateIndexRequestBuilder(this.testClient, CreateIndexAction.INSTANCE);
builder.setSource("{\""+KEY+"\" : \""+VALUE+"\"}", XContentType.JSON);
ElasticsearchParseException e = expectThrows(ElasticsearchParseException.class,
() -> {builder.setSource("{\""+KEY+"\" : \""+VALUE+"\"}", XContentType.JSON);});
assertEquals(String.format(Locale.ROOT, "unknown key [%s] for create index", KEY), e.getMessage());
builder.setSource("{\"settings\" : {\""+KEY+"\" : \""+VALUE+"\"}}", XContentType.JSON);
assertEquals(VALUE, builder.request().settings().get(KEY));
XContentBuilder xContent = XContentFactory.jsonBuilder().startObject().field(KEY, VALUE).endObject();
XContentBuilder xContent = XContentFactory.jsonBuilder().startObject()
.startObject("settings").field(KEY, VALUE).endObject().endObject();
xContent.close();
builder.setSource(xContent);
assertEquals(VALUE, builder.request().settings().get(KEY));
ByteArrayOutputStream docOut = new ByteArrayOutputStream();
XContentBuilder doc = XContentFactory.jsonBuilder(docOut).startObject().field(KEY, VALUE).endObject();
XContentBuilder doc = XContentFactory.jsonBuilder(docOut).startObject()
.startObject("settings").field(KEY, VALUE).endObject().endObject();
doc.close();
builder.setSource(docOut.toByteArray(), XContentType.JSON);
assertEquals(VALUE, builder.request().settings().get(KEY));

View File

@ -19,6 +19,7 @@
package org.elasticsearch.action.admin.indices.create;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.xcontent.XContentType;
@ -45,4 +46,27 @@ public class CreateIndexRequestTests extends ESTestCase {
}
}
}
public void testTopLevelKeys() throws IOException {
String createIndex =
"{\n"
+ " \"FOO_SHOULD_BE_ILLEGAL_HERE\": {\n"
+ " \"BAR_IS_THE_SAME\": 42\n"
+ " },\n"
+ " \"mappings\": {\n"
+ " \"test\": {\n"
+ " \"properties\": {\n"
+ " \"field1\": {\n"
+ " \"type\": \"text\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}";
CreateIndexRequest request = new CreateIndexRequest();
ElasticsearchParseException e = expectThrows(ElasticsearchParseException.class,
() -> {request.source(createIndex, XContentType.JSON);});
assertEquals("unknown key [FOO_SHOULD_BE_ILLEGAL_HERE] for create index", e.getMessage());
}
}

View File

@ -86,25 +86,27 @@ Here is an example:
--------------------------------------------------
PUT /compound_word_example
{
"index": {
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["dictionary_decompounder", "hyphenation_decompounder"]
}
},
"filter": {
"dictionary_decompounder": {
"type": "dictionary_decompounder",
"word_list": ["one", "two", "three"]
"settings": {
"index": {
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["dictionary_decompounder", "hyphenation_decompounder"]
}
},
"hyphenation_decompounder": {
"type" : "hyphenation_decompounder",
"word_list_path": "analysis/example_word_list.txt",
"hyphenation_patterns_path": "analysis/hyphenation_patterns.xml",
"max_subword_size": 22
"filter": {
"dictionary_decompounder": {
"type": "dictionary_decompounder",
"word_list": ["one", "two", "three"]
},
"hyphenation_decompounder": {
"type" : "hyphenation_decompounder",
"word_list_path": "analysis/example_word_list.txt",
"hyphenation_patterns_path": "analysis/hyphenation_patterns.xml",
"max_subword_size": 22
}
}
}
}

View File

@ -3,8 +3,9 @@
indices.create:
index: smb-test
body:
index:
store.type: smb_mmap_fs
settings:
index:
store.type: smb_mmap_fs
- do:
index:

View File

@ -47,7 +47,7 @@
- do:
indices.create:
index: test
body: { "index.number_of_shards": 1, "index.number_of_replicas": 9 }
body: { "settings": { "index.number_of_shards": 1, "index.number_of_replicas": 9 } }
- do:
cluster.state: