Skip to content

Commit f60dd5f

Browse files
authored
Validation for index name expressions (#139023) (#139628)
Add validation for index name expressions used in security roles and API keys: - An expression that starts with slash (/) must be a valid Lucene regular expression - Commas are not allowed outside of a regular expression
1 parent a4da4ad commit f60dd5f

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

docs/changelog/139023.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 139023
2+
summary: Add comma delimiter validation to index name expressions in roles and API keys
3+
area: Security
4+
type: bug
5+
issues: []

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/role/RoleDescriptorRequestValidator.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
package org.elasticsearch.xpack.core.security.action.role;
99

10+
import org.apache.lucene.util.automaton.RegExp;
1011
import org.elasticsearch.action.ActionRequestValidationException;
1112
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
1213
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
@@ -140,6 +141,24 @@ private static ActionRequestValidationException validateIndexNameExpression(
140141
validationException
141142
);
142143
}
144+
if (indexNameExpression != null) {
145+
if (indexNameExpression.startsWith("/")) {
146+
if (indexNameExpression.length() == 1 || indexNameExpression.endsWith("/") == false) {
147+
return addValidationError("invalid regular expression pattern [" + indexNameExpression + "]", validationException);
148+
}
149+
String regex = indexNameExpression.substring(1, indexNameExpression.length() - 1);
150+
try {
151+
new RegExp(regex);
152+
} catch (IllegalArgumentException e) {
153+
return addValidationError("invalid regular expression pattern [" + indexNameExpression + "]", validationException);
154+
}
155+
} else if (indexNameExpression.contains(",")) {
156+
validationException = addValidationError(
157+
"commas [,] are not allowed in the index name expression [" + indexNameExpression + "]",
158+
validationException
159+
);
160+
}
161+
}
143162
return validationException;
144163
}
145164
}

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/role/RoleDescriptorRequestValidatorTests.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,57 @@ public void testSelectorsValidation() {
7373
}
7474
}
7575

76+
public void testCommaValidation() {
77+
String[] invalidIndexNames = {
78+
"index1,index2",
79+
"logs-*,metrics-*",
80+
",leading",
81+
"trailing,",
82+
"a,b,c",
83+
"my,index",
84+
randomAlphaOfLengthBetween(3, 6) + "," + randomAlphaOfLengthBetween(3, 6) };
85+
for (String indexName : invalidIndexNames) {
86+
validateAndAssertCommaNotAllowed(roleWithIndexPrivileges(indexName), indexName);
87+
validateAndAssertCommaNotAllowed(roleWithRemoteIndexPrivileges(indexName), indexName);
88+
}
89+
90+
String[] validIndexNames = {
91+
"no-comma",
92+
"logs-*",
93+
"*",
94+
"",
95+
null,
96+
"index:with:colons",
97+
"/regex,with,commas/",
98+
"/[a-z]+,[0-9]+/",
99+
"/logs-(foo|bar),.*/" };
100+
for (String indexName : validIndexNames) {
101+
validateAndAssertNoException(roleWithIndexPrivileges(indexName), indexName);
102+
validateAndAssertNoException(roleWithRemoteIndexPrivileges(indexName), indexName);
103+
}
104+
}
105+
106+
public void testRegularExpressionValidation() {
107+
String[] invalidRegexPatterns = { "/", "/unclosed", "/[invalid/", "/(/", "/[a-/" };
108+
for (String indexName : invalidRegexPatterns) {
109+
validateAndAssertInvalidRegex(roleWithIndexPrivileges(indexName), indexName);
110+
validateAndAssertInvalidRegex(roleWithRemoteIndexPrivileges(indexName), indexName);
111+
}
112+
113+
String[] validRegexPatterns = {
114+
"/logs-.*/",
115+
"/[a-z]+/",
116+
"/[abc]{2,5}/",
117+
"/index-[0-9]{4}/",
118+
"/.*/",
119+
"/*/",
120+
"/logs-[0-9]{4}\\.[0-9]{2}\\.[0-9]{2}/" };
121+
for (String indexName : validRegexPatterns) {
122+
validateAndAssertNoException(roleWithIndexPrivileges(indexName), indexName);
123+
validateAndAssertNoException(roleWithRemoteIndexPrivileges(indexName), indexName);
124+
}
125+
}
126+
76127
private static void validateAndAssertSelectorNotAllowed(RoleDescriptor roleDescriptor, String indexName) {
77128
var validationException = RoleDescriptorRequestValidator.validate(roleDescriptor);
78129
assertThat("expected validation exception for " + indexName, validationException, notNullValue());
@@ -82,6 +133,21 @@ private static void validateAndAssertSelectorNotAllowed(RoleDescriptor roleDescr
82133
);
83134
}
84135

136+
private static void validateAndAssertCommaNotAllowed(RoleDescriptor roleDescriptor, String indexName) {
137+
var validationException = RoleDescriptorRequestValidator.validate(roleDescriptor);
138+
assertThat("expected validation exception for " + indexName, validationException, notNullValue());
139+
assertThat(
140+
validationException.validationErrors(),
141+
containsInAnyOrder("commas [,] are not allowed in the index name expression [" + indexName + "]")
142+
);
143+
}
144+
145+
private static void validateAndAssertInvalidRegex(RoleDescriptor roleDescriptor, String indexName) {
146+
var validationException = RoleDescriptorRequestValidator.validate(roleDescriptor);
147+
assertThat("expected validation exception for " + indexName, validationException, notNullValue());
148+
assertThat(validationException.validationErrors(), containsInAnyOrder("invalid regular expression pattern [" + indexName + "]"));
149+
}
150+
85151
private static void validateAndAssertNoException(RoleDescriptor roleDescriptor, String indexName) {
86152
var validationException = RoleDescriptorRequestValidator.validate(roleDescriptor);
87153
assertThat("expected no validation exception for " + indexName, validationException, nullValue());

0 commit comments

Comments
 (0)