security: ignore empty query value in roles

Users are allowed to create query objects with an empty string value as we do
not currently validate the input against a query parser. In this case, we can ignore
the empty value when parsing the role. If we pass an empty BytesReference in
the role then trying to determine the XContentType will fail in the
SecurityIndexSearcherWrapper.

Closes elastic/elasticsearch#2997

Original commit: elastic/x-pack-elasticsearch@fc593943c4
This commit is contained in:
jaymode 2016-08-03 11:06:02 -04:00
parent 196f74984c
commit 60cb867d47
2 changed files with 21 additions and 2 deletions

View File

@ -260,8 +260,14 @@ public class RoleDescriptor implements ToXContent {
XContentBuilder builder = JsonXContent.contentBuilder(); XContentBuilder builder = JsonXContent.contentBuilder();
XContentHelper.copyCurrentStructure(builder.generator(), parser); XContentHelper.copyCurrentStructure(builder.generator(), parser);
query = builder.string(); query = builder.string();
} else { } else if (token == XContentParser.Token.VALUE_STRING){
query = parser.textOrNull(); final String text = parser.text();
if (text.isEmpty() == false) {
query = text;
}
} else if (token != XContentParser.Token.VALUE_NULL) {
throw new ElasticsearchParseException("failed to parse indices privileges for role [{}]. expected field [{}] " +
"value to be null, a string, or an object, but found [{}] instead", roleName, currentFieldName, token);
} }
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Fields.PRIVILEGES)) { } else if (ParseFieldMatcher.STRICT.match(currentFieldName, Fields.PRIVILEGES)) {
privileges = readStringArray(roleName, parser, true); privileges = readStringArray(roleName, parser, true);

View File

@ -96,6 +96,7 @@ public class RoleDescriptorTests extends ESTestCase {
assertEquals(1, rd.getIndicesPrivileges().length); assertEquals(1, rd.getIndicesPrivileges().length);
assertArrayEquals(new String[] { "idx1", "idx2" }, rd.getIndicesPrivileges()[0].getIndices()); assertArrayEquals(new String[] { "idx1", "idx2" }, rd.getIndicesPrivileges()[0].getIndices());
assertArrayEquals(new String[] { "m", "n" }, rd.getRunAs()); assertArrayEquals(new String[] { "m", "n" }, rd.getRunAs());
assertNull(rd.getIndicesPrivileges()[0].getQuery());
q = "{\"cluster\":[\"a\", \"b\"], \"metadata\":{\"foo\":\"bar\"}}"; q = "{\"cluster\":[\"a\", \"b\"], \"metadata\":{\"foo\":\"bar\"}}";
rd = RoleDescriptor.parse("test", new BytesArray(q)); rd = RoleDescriptor.parse("test", new BytesArray(q));
@ -126,4 +127,16 @@ public class RoleDescriptorTests extends ESTestCase {
final RoleDescriptor serialized = RoleDescriptor.readFrom(streamInput); final RoleDescriptor serialized = RoleDescriptor.readFrom(streamInput);
assertEquals(descriptor, serialized); assertEquals(descriptor, serialized);
} }
public void testParseEmptyQuery() throws Exception {
String json = "{\"cluster\":[\"a\", \"b\"], \"run_as\": [\"m\", \"n\"], \"indices\": [{\"names\": [\"idx1\",\"idx2\"], " +
"\"privileges\": [\"p1\", \"p2\"], \"query\": \"\"}]}";
RoleDescriptor rd = RoleDescriptor.parse("test", new BytesArray(json));
assertEquals("test", rd.getName());
assertArrayEquals(new String[] { "a", "b" }, rd.getClusterPrivileges());
assertEquals(1, rd.getIndicesPrivileges().length);
assertArrayEquals(new String[] { "idx1", "idx2" }, rd.getIndicesPrivileges()[0].getIndices());
assertArrayEquals(new String[] { "m", "n" }, rd.getRunAs());
assertNull(rd.getIndicesPrivileges()[0].getQuery());
}
} }