Skip to content

Commit 314b9ca

Browse files
authored
[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 4167c14 commit 314b9ca

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
@@ -21,6 +21,7 @@
2121
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata.AutoFollowPattern;
2222

2323
import java.io.IOException;
24+
import java.nio.charset.StandardCharsets;
2425
import java.util.List;
2526
import java.util.Objects;
2627

@@ -44,8 +45,8 @@ public AcknowledgedResponse newResponse() {
4445
public static class Request extends AcknowledgedRequest<Request> implements ToXContentObject {
4546

4647
private static final ObjectParser<Request, String> PARSER = new ObjectParser<>("put_auto_follow_pattern_request", Request::new);
47-
4848
private static final ParseField NAME_FIELD = new ParseField("name");
49+
private static final int MAX_NAME_BYTES = 255;
4950

5051
static {
5152
PARSER.declareString(Request::setName, NAME_FIELD);
@@ -119,6 +120,21 @@ public ActionRequestValidationException validate() {
119120
if (name == null) {
120121
validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] is missing", validationException);
121122
}
123+
if (name != null) {
124+
if (name.contains(",")) {
125+
validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] name must not contain a ','",
126+
validationException);
127+
}
128+
if (name.startsWith("_")) {
129+
validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] name must not start with '_'",
130+
validationException);
131+
}
132+
int byteCount = name.getBytes(StandardCharsets.UTF_8).length;
133+
if (byteCount > MAX_NAME_BYTES) {
134+
validationException = addValidationError("[" + NAME_FIELD.getPreferredName() + "] name is too long (" +
135+
byteCount + " > " + MAX_NAME_BYTES + ")", validationException);
136+
}
137+
}
122138
if (remoteCluster == null) {
123139
validationException = addValidationError("[" + REMOTE_CLUSTER_FIELD.getPreferredName() +
124140
"] is missing", validationException);

0 commit comments

Comments
 (0)