Skip to content

Commit 0607178

Browse files
authored
Enforce limitations on ILM policy names (elastic#35104)
Enforces restrictions on ILM policy names to ensure we don't accept policy names the system can't handle, or may reserve for future use.
1 parent 17993e1 commit 0607178

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-0
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/LifecyclePolicy.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
2222

2323
import java.io.IOException;
24+
import java.nio.charset.StandardCharsets;
2425
import java.util.ArrayList;
2526
import java.util.Collections;
2627
import java.util.List;
2728
import java.util.ListIterator;
2829
import java.util.Map;
2930
import java.util.Objects;
31+
import java.util.function.BiFunction;
3032
import java.util.function.Function;
3133
import java.util.stream.Collectors;
3234

@@ -40,6 +42,7 @@
4042
public class LifecyclePolicy extends AbstractDiffable<LifecyclePolicy>
4143
implements ToXContentObject, Diffable<LifecyclePolicy> {
4244
private static final Logger logger = LogManager.getLogger(LifecyclePolicy.class);
45+
private static final int MAX_INDEX_NAME_BYTES = 255;
4346

4447
public static final ParseField PHASES_FIELD = new ParseField("phases");
4548

@@ -241,6 +244,30 @@ public boolean isActionSafe(StepKey stepKey) {
241244
}
242245
}
243246

247+
/**
248+
* Validate the name for an policy against some static rules. Intended to match
249+
* {@link org.elasticsearch.cluster.metadata.MetaDataCreateIndexService#validateIndexOrAliasName(String, BiFunction)}
250+
* @param policy the policy name to validate
251+
* @throws IllegalArgumentException if the name is invalid
252+
*/
253+
public static void validatePolicyName(String policy) {
254+
if (policy.contains(",")) {
255+
throw new IllegalArgumentException("invalid policy name [" + policy + "]: must not contain ','");
256+
}
257+
if (policy.contains(" ")) {
258+
throw new IllegalArgumentException("invalid policy name [" + policy + "]: must not contain spaces");
259+
}
260+
if (policy.charAt(0) == '_') {
261+
throw new IllegalArgumentException("invalid policy name [" + policy + "]: must not start with '_'");
262+
}
263+
int byteCount = 0;
264+
byteCount = policy.getBytes(StandardCharsets.UTF_8).length;
265+
if (byteCount > MAX_INDEX_NAME_BYTES) {
266+
throw new IllegalArgumentException("invalid policy name [" + policy + "]: name is too long, (" + byteCount + " > " +
267+
MAX_INDEX_NAME_BYTES + ")");
268+
}
269+
}
270+
244271
@Override
245272
public int hashCode() {
246273
return Objects.hash(name, phases);

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/LifecyclePolicyTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,4 +316,20 @@ public void testIsActionSafe() {
316316

317317
assertTrue(policy.isActionSafe(new StepKey("new", randomAlphaOfLength(10), randomAlphaOfLength(10))));
318318
}
319+
320+
public void testValidatePolicyName() {
321+
expectThrows(IllegalArgumentException.class, () -> LifecyclePolicy.validatePolicyName(randomAlphaOfLengthBetween(0,10) +
322+
"," + randomAlphaOfLengthBetween(0,10)));
323+
expectThrows(IllegalArgumentException.class, () -> LifecyclePolicy.validatePolicyName(randomAlphaOfLengthBetween(0,10) +
324+
" " + randomAlphaOfLengthBetween(0,10)));
325+
expectThrows(IllegalArgumentException.class, () -> LifecyclePolicy.validatePolicyName("_" + randomAlphaOfLengthBetween(1, 20)));
326+
expectThrows(IllegalArgumentException.class, () -> LifecyclePolicy.validatePolicyName(randomAlphaOfLengthBetween(256, 1000)));
327+
328+
LifecyclePolicy.validatePolicyName(randomAlphaOfLengthBetween(1,10) + "_" + randomAlphaOfLengthBetween(0,10));
329+
330+
LifecyclePolicy.validatePolicyName(randomAlphaOfLengthBetween(0,10) + "-" + randomAlphaOfLengthBetween(0,10));
331+
LifecyclePolicy.validatePolicyName(randomAlphaOfLengthBetween(0,10) + "+" + randomAlphaOfLengthBetween(0,10));
332+
333+
LifecyclePolicy.validatePolicyName(randomAlphaOfLengthBetween(1,255));
334+
}
319335
}

x-pack/plugin/ilm/qa/multi-node/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeSeriesLifecycleActionsIT.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
import java.io.IOException;
3939
import java.io.InputStream;
40+
import java.io.UnsupportedEncodingException;
4041
import java.util.Collections;
4142
import java.util.HashMap;
4243
import java.util.List;
@@ -46,6 +47,7 @@
4647

4748
import static java.util.Collections.singletonMap;
4849
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
50+
import static org.hamcrest.Matchers.containsString;
4951
import static org.hamcrest.Matchers.equalTo;
5052
import static org.hamcrest.Matchers.greaterThan;
5153
import static org.hamcrest.Matchers.not;
@@ -435,6 +437,26 @@ public void testNonexistentPolicy() throws Exception {
435437

436438
}
437439

440+
public void testInvalidPolicyNames() throws UnsupportedEncodingException {
441+
ResponseException ex;
442+
443+
policy = randomAlphaOfLengthBetween(0,10) + "," + randomAlphaOfLengthBetween(0,10);
444+
ex = expectThrows(ResponseException.class, () -> createNewSingletonPolicy("delete", new DeleteAction()));
445+
assertThat(ex.getCause().getMessage(), containsString("invalid policy name"));
446+
447+
policy = randomAlphaOfLengthBetween(0,10) + "%20" + randomAlphaOfLengthBetween(0,10);
448+
ex = expectThrows(ResponseException.class, () -> createNewSingletonPolicy("delete", new DeleteAction()));
449+
assertThat(ex.getCause().getMessage(), containsString("invalid policy name"));
450+
451+
policy = "_" + randomAlphaOfLengthBetween(1, 20);
452+
ex = expectThrows(ResponseException.class, () -> createNewSingletonPolicy("delete", new DeleteAction()));
453+
assertThat(ex.getMessage(), containsString("invalid policy name"));
454+
455+
policy = randomAlphaOfLengthBetween(256, 1000);
456+
ex = expectThrows(ResponseException.class, () -> createNewSingletonPolicy("delete", new DeleteAction()));
457+
assertThat(ex.getMessage(), containsString("invalid policy name"));
458+
}
459+
438460
private void createFullPolicy(TimeValue hotTime) throws IOException {
439461
Map<String, LifecycleAction> warmActions = new HashMap<>();
440462
warmActions.put(ForceMergeAction.NAME, new ForceMergeAction(1));

x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/TransportPutLifecycleAction.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.elasticsearch.transport.TransportService;
2424
import org.elasticsearch.xpack.core.ClientHelper;
2525
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata;
26+
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
2627
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata;
2728
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction;
2829
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction.Request;
@@ -66,6 +67,7 @@ protected void masterOperation(Request request, ClusterState state, ActionListen
6667
Map<String, String> filteredHeaders = threadPool.getThreadContext().getHeaders().entrySet().stream()
6768
.filter(e -> ClientHelper.SECURITY_HEADER_FILTERS.contains(e.getKey()))
6869
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
70+
LifecyclePolicy.validatePolicyName(request.getPolicy().getName());
6971
clusterService.submitStateUpdateTask("put-lifecycle-" + request.getPolicy().getName(),
7072
new AckedClusterStateUpdateTask<Response>(request, listener) {
7173
@Override

0 commit comments

Comments
 (0)