Skip to content

Commit 6a781f6

Browse files
committed
[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
1 parent 59493a2 commit 6a781f6

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/action/PutAutoFollowPatternRequestTests.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,65 @@ public void testValidate() {
123123
validationException = request.validate();
124124
assertThat(validationException, nullValue());
125125
}
126+
127+
public void testValidateName() {
128+
PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request();
129+
request.setRemoteCluster("_alias");
130+
request.setLeaderIndexPatterns(Collections.singletonList("logs-*"));
131+
132+
request.setName("name");
133+
ActionRequestValidationException validationException = request.validate();
134+
assertThat(validationException, nullValue());
135+
}
136+
137+
public void testValidateNameComma() {
138+
PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request();
139+
request.setRemoteCluster("_alias");
140+
request.setLeaderIndexPatterns(Collections.singletonList("logs-*"));
141+
142+
request.setName("name1,name2");
143+
ActionRequestValidationException validationException = request.validate();
144+
assertThat(validationException, notNullValue());
145+
assertThat(validationException.getMessage(), containsString("name must not contain a ','"));
146+
}
147+
148+
public void testValidateNameLeadingUnderscore() {
149+
PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request();
150+
request.setRemoteCluster("_alias");
151+
request.setLeaderIndexPatterns(Collections.singletonList("logs-*"));
152+
153+
request.setName("_name");
154+
ActionRequestValidationException validationException = request.validate();
155+
assertThat(validationException, notNullValue());
156+
assertThat(validationException.getMessage(), containsString("name must not start with '_'"));
157+
}
158+
159+
public void testValidateNameUnderscores() {
160+
PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request();
161+
request.setRemoteCluster("_alias");
162+
request.setLeaderIndexPatterns(Collections.singletonList("logs-*"));
163+
164+
request.setName("n_a_m_e_");
165+
ActionRequestValidationException validationException = request.validate();
166+
assertThat(validationException, nullValue());
167+
}
168+
169+
public void testValidateNameTooLong() {
170+
PutAutoFollowPatternAction.Request request = new PutAutoFollowPatternAction.Request();
171+
request.setRemoteCluster("_alias");
172+
request.setLeaderIndexPatterns(Collections.singletonList("logs-*"));
173+
174+
StringBuilder stringBuilder = new StringBuilder();
175+
for (int i = 0; i < 256; i++) {
176+
stringBuilder.append('x');
177+
}
178+
request.setName(stringBuilder.toString());
179+
ActionRequestValidationException validationException = request.validate();
180+
assertThat(validationException, notNullValue());
181+
assertThat(validationException.getMessage(), containsString("name is too long (256 > 255)"));
182+
183+
request.setName("name");
184+
validationException = request.validate();
185+
assertThat(validationException, nullValue());
186+
}
126187
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ccr/action/PutAutoFollowPatternAction.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata.AutoFollowPattern;
2424

2525
import java.io.IOException;
26+
import java.nio.charset.StandardCharsets;
2627
import java.util.List;
2728
import java.util.Objects;
2829

@@ -52,8 +53,8 @@ public RequestBuilder newRequestBuilder(ElasticsearchClient client) {
5253
public static class Request extends AcknowledgedRequest<Request> implements ToXContentObject {
5354

5455
private static final ObjectParser<Request, String> PARSER = new ObjectParser<>("put_auto_follow_pattern_request", Request::new);
55-
5656
private static final ParseField NAME_FIELD = new ParseField("name");
57+
private static final int MAX_NAME_BYTES = 255;
5758

5859
static {
5960
PARSER.declareString(Request::setName, NAME_FIELD);
@@ -127,6 +128,21 @@ public ActionRequestValidationException validate() {
127128
if (name == null) {
128129
validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] is missing", validationException);
129130
}
131+
if (name != null) {
132+
if (name.contains(",")) {
133+
validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] name must not contain a ','",
134+
validationException);
135+
}
136+
if (name.startsWith("_")) {
137+
validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] name must not start with '_'",
138+
validationException);
139+
}
140+
int byteCount = name.getBytes(StandardCharsets.UTF_8).length;
141+
if (byteCount > MAX_NAME_BYTES) {
142+
validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] name is too long (" +
143+
byteCount + " > " + MAX_NAME_BYTES + ")", validationException);
144+
}
145+
}
130146
if (remoteCluster == null) {
131147
validationException = addValidationError("[" + REMOTE_CLUSTER_FIELD.getPreferredName() +
132148
"] is missing", validationException);

0 commit comments

Comments
 (0)