Validate settings specified in index templates at template creation time

Previously settings specified in index templates were not validated upon
template creation. Creating an index from an index template with invalid
settings could lead to cluster stability issues because creation of such
indexes would bypass index settings validation.

This commit adds validation of settings specified in index templates at
template creation time. This works by routing the index template
settings through the index settings validation mechanism.

Closes #12865
This commit is contained in:
Jason Tedor 2015-08-14 10:03:06 -07:00
parent 3893544f98
commit b88d2f6255
2 changed files with 91 additions and 1 deletions

View File

@ -34,6 +34,7 @@ import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.indices.IndexCreationException;
import org.elasticsearch.indices.IndexTemplateAlreadyExistsException;
import org.elasticsearch.indices.IndexTemplateMissingException;
import org.elasticsearch.indices.InvalidIndexTemplateException;
@ -50,12 +51,14 @@ public class MetaDataIndexTemplateService extends AbstractComponent {
private final ClusterService clusterService;
private final AliasValidator aliasValidator;
private final MetaDataCreateIndexService metaDataCreateIndexService;
@Inject
public MetaDataIndexTemplateService(Settings settings, ClusterService clusterService, AliasValidator aliasValidator) {
public MetaDataIndexTemplateService(Settings settings, ClusterService clusterService, MetaDataCreateIndexService metaDataCreateIndexService, AliasValidator aliasValidator) {
super(settings);
this.clusterService = clusterService;
this.aliasValidator = aliasValidator;
this.metaDataCreateIndexService = metaDataCreateIndexService;
}
public void removeTemplates(final RemoveRequest request, final RemoveListener listener) {
@ -207,6 +210,12 @@ public class MetaDataIndexTemplateService extends AbstractComponent {
throw new InvalidIndexTemplateException(request.name, "template must not container the following characters " + Strings.INVALID_FILENAME_CHARS);
}
try {
metaDataCreateIndexService.validateIndexSettings(request.name, request.settings);
} catch (IndexCreationException exception) {
throw new InvalidIndexTemplateException(request.name, exception.getDetailedMessage());
}
for (Alias alias : request.aliases) {
//we validate the alias only partially, as we don't know yet to which index it'll get applied to
aliasValidator.validateAliasStandalone(alias);

View File

@ -0,0 +1,81 @@
/*
* 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.action.admin.indices.template.put;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexTemplateFilter;
import org.elasticsearch.cluster.metadata.MetaDataCreateIndexService;
import org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService;
import org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService.PutRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.indices.InvalidIndexTemplateException;
import org.elasticsearch.test.ESTestCase;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class MetaDataIndexTemplateServiceTests extends ESTestCase {
@Test
public void testIndexTemplateInvalidNumberOfShards() throws IOException {
MetaDataCreateIndexService createIndexService = new MetaDataCreateIndexService(
Settings.EMPTY,
null,
null,
null,
null,
null,
Version.CURRENT,
null,
Sets.<IndexTemplateFilter>newHashSet(),
null,
null
);
MetaDataIndexTemplateService service = new MetaDataIndexTemplateService(Settings.EMPTY, null, createIndexService, null);
PutRequest request = new PutRequest("test", "test_shards");
request.template("test_shards*");
Map<String, Object> map = Maps.newHashMap();
map.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, "0");
request.settings(Settings.settingsBuilder().put(map).build());
final List<Throwable> throwables = Lists.newArrayList();
service.putTemplate(request, new MetaDataIndexTemplateService.PutListener() {
@Override
public void onResponse(MetaDataIndexTemplateService.PutResponse response) {
}
@Override
public void onFailure(Throwable t) {
throwables.add(t);
}
});
assertEquals(throwables.size(), 1);
assertTrue(throwables.get(0) instanceof InvalidIndexTemplateException);
assertTrue(throwables.get(0).getMessage().contains("index must have 1 or more primary shards"));
}
}