From e56aceb98cc59bce4d42f6e528be81c59a157838 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Wed, 7 Nov 2018 20:16:26 +0100 Subject: [PATCH] [CCR] Enforce auto follow pattern name restrictions (#35197) An auto follow pattern: * cannot start with `_` * cannot contain a `,` * can be encoded in UTF-8 * the length of UTF-8 encoded bytes is no longer than 255 bytes --- .../PutAutoFollowPatternRequestTests.java | 61 +++++++++++++++++++ .../action/PutAutoFollowPatternAction.java | 18 +++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/action/PutAutoFollowPatternRequestTests.java b/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/action/PutAutoFollowPatternRequestTests.java index 47da4aee1677e..59d00a328e553 100644 --- a/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/action/PutAutoFollowPatternRequestTests.java +++ b/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/action/PutAutoFollowPatternRequestTests.java @@ -123,4 +123,65 @@ public void testValidate() { validationException = request.validate(); assertThat(validationException, nullValue()); } + + public void testValidateName() { + PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request(); + request.setRemoteCluster("_alias"); + request.setLeaderIndexPatterns(Collections.singletonList("logs-*")); + + request.setName("name"); + ActionRequestValidationException validationException = request.validate(); + assertThat(validationException, nullValue()); + } + + public void testValidateNameComma() { + PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request(); + request.setRemoteCluster("_alias"); + request.setLeaderIndexPatterns(Collections.singletonList("logs-*")); + + request.setName("name1,name2"); + ActionRequestValidationException validationException = request.validate(); + assertThat(validationException, notNullValue()); + assertThat(validationException.getMessage(), containsString("name must not contain a ','")); + } + + public void testValidateNameLeadingUnderscore() { + PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request(); + request.setRemoteCluster("_alias"); + request.setLeaderIndexPatterns(Collections.singletonList("logs-*")); + + request.setName("_name"); + ActionRequestValidationException validationException = request.validate(); + assertThat(validationException, notNullValue()); + assertThat(validationException.getMessage(), containsString("name must not start with '_'")); + } + + public void testValidateNameUnderscores() { + PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request(); + request.setRemoteCluster("_alias"); + request.setLeaderIndexPatterns(Collections.singletonList("logs-*")); + + request.setName("n_a_m_e_"); + ActionRequestValidationException validationException = request.validate(); + assertThat(validationException, nullValue()); + } + + public void testValidateNameTooLong() { + PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request(); + request.setRemoteCluster("_alias"); + request.setLeaderIndexPatterns(Collections.singletonList("logs-*")); + + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < 256; i++) { + stringBuilder.append('x'); + } + request.setName(stringBuilder.toString()); + ActionRequestValidationException validationException = request.validate(); + assertThat(validationException, notNullValue()); + assertThat(validationException.getMessage(), containsString("name is too long (256 > 255)")); + + request.setName("name"); + validationException = request.validate(); + assertThat(validationException, nullValue()); + } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ccr/action/PutAutoFollowPatternAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ccr/action/PutAutoFollowPatternAction.java index ac2e008d0b267..1db49a78636b6 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ccr/action/PutAutoFollowPatternAction.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ccr/action/PutAutoFollowPatternAction.java @@ -23,6 +23,7 @@ import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata.AutoFollowPattern; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Objects; @@ -52,8 +53,8 @@ public RequestBuilder newRequestBuilder(ElasticsearchClient client) { public static class Request extends AcknowledgedRequest implements ToXContentObject { private static final ObjectParser PARSER = new ObjectParser<>("put_auto_follow_pattern_request", Request::new); - private static final ParseField NAME_FIELD = new ParseField("name"); + private static final int MAX_NAME_BYTES = 255; static { PARSER.declareString(Request::setName, NAME_FIELD); @@ -127,6 +128,21 @@ public ActionRequestValidationException validate() { if (name == null) { validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] is missing", validationException); } + if (name != null) { + if (name.contains(",")) { + validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] name must not contain a ','", + validationException); + } + if (name.startsWith("_")) { + validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] name must not start with '_'", + validationException); + } + int byteCount = name.getBytes(StandardCharsets.UTF_8).length; + if (byteCount > MAX_NAME_BYTES) { + validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] name is too long (" + + byteCount + " > " + MAX_NAME_BYTES + ")", validationException); + } + } if (remoteCluster == null) { validationException = addValidationError("[" + REMOTE_CLUSTER_FIELD.getPreferredName() + "] is missing", validationException);