Fix security source filtering. (elastic/x-pack-elasticsearch#561)

Source filtering is currently written as if the fact that an object is accepted
means that all sub fields and objects are implicitly accepted, which is not
true.

Original commit: elastic/x-pack-elasticsearch@afc4440e7a
This commit is contained in:
Adrien Grand 2017-02-14 17:44:20 +01:00 committed by GitHub
parent 6e411c6118
commit ac8f3ffec4
2 changed files with 69 additions and 15 deletions

View File

@ -160,9 +160,7 @@ public final class FieldSubsetReader extends FilterLeafReader {
Object value = entry.getValue(); Object value = entry.getValue();
if (includeAutomaton.isAccept(state)) { if (value instanceof Map) {
filtered.put(key, value);
} else if (value instanceof Map) {
state = includeAutomaton.step(state, '.'); state = includeAutomaton.step(state, '.');
if (state == -1) { if (state == -1) {
continue; continue;
@ -179,6 +177,8 @@ public final class FieldSubsetReader extends FilterLeafReader {
if (filteredValue.isEmpty() == false) { if (filteredValue.isEmpty() == false) {
filtered.put(key, filteredValue); filtered.put(key, filteredValue);
} }
} else if (includeAutomaton.isAccept(state)) {
filtered.put(key, value);
} }
} }
return filtered; return filtered;
@ -202,6 +202,8 @@ public final class FieldSubsetReader extends FilterLeafReader {
if (filteredValue.isEmpty() == false) { if (filteredValue.isEmpty() == false) {
filtered.add(filteredValue); filtered.add(filteredValue);
} }
} else if (includeAutomaton.isAccept(initialState)) {
filtered.add(value);
} }
} }
return filtered; return filtered;

View File

@ -41,6 +41,7 @@ import org.apache.lucene.util.TestUtil;
import org.apache.lucene.util.automaton.Automata; import org.apache.lucene.util.automaton.Automata;
import org.apache.lucene.util.automaton.Automaton; import org.apache.lucene.util.automaton.Automaton;
import org.apache.lucene.util.automaton.CharacterRunAutomaton; import org.apache.lucene.util.automaton.CharacterRunAutomaton;
import org.apache.lucene.util.automaton.Operations;
import org.elasticsearch.index.mapper.FieldNamesFieldMapper; import org.elasticsearch.index.mapper.FieldNamesFieldMapper;
import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.index.mapper.SourceFieldMapper;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
@ -625,7 +626,7 @@ public class FieldSubsetReaderTests extends ESTestCase {
assertEquals(expected, filtered); assertEquals(expected, filtered);
// include on object // include on inner wildcard
map = new HashMap<>(); map = new HashMap<>();
Map<String, Object> subMap = new HashMap<>(); Map<String, Object> subMap = new HashMap<>();
subMap.put("bar", 42); subMap.put("bar", 42);
@ -633,14 +634,6 @@ public class FieldSubsetReaderTests extends ESTestCase {
map.put("foo", subMap); map.put("foo", subMap);
map.put("bar", "baz"); map.put("bar", "baz");
include = new CharacterRunAutomaton(Automata.makeString("foo"));
filtered = FieldSubsetReader.filter(map, include, 0);
expected = new HashMap<>();
expected.put("foo", subMap);
assertEquals(expected, filtered);
// include on inner wildcard
include = new CharacterRunAutomaton(Automatons.patterns("foo.*")); include = new CharacterRunAutomaton(Automatons.patterns("foo.*"));
filtered = FieldSubsetReader.filter(map, include, 0); filtered = FieldSubsetReader.filter(map, include, 0);
expected = new HashMap<>(); expected = new HashMap<>();
@ -652,7 +645,6 @@ public class FieldSubsetReaderTests extends ESTestCase {
include = new CharacterRunAutomaton(Automatons.patterns("*.bar")); include = new CharacterRunAutomaton(Automatons.patterns("*.bar"));
filtered = FieldSubsetReader.filter(map, include, 0); filtered = FieldSubsetReader.filter(map, include, 0);
expected = new HashMap<>(); expected = new HashMap<>();
expected = new HashMap<>();
subMap = new HashMap<>(); subMap = new HashMap<>();
subMap.put("bar", 42); subMap.put("bar", 42);
expected.put("foo", subMap); expected.put("foo", subMap);
@ -665,6 +657,26 @@ public class FieldSubsetReaderTests extends ESTestCase {
assertEquals(expected, filtered); assertEquals(expected, filtered);
// exclude on exact value
include = new CharacterRunAutomaton(Operations.minus(
Automata.makeAnyString(), Automatons.patterns("foo.bar"),
Operations.DEFAULT_MAX_DETERMINIZED_STATES));
filtered = FieldSubsetReader.filter(map, include, 0);
expected = new HashMap<>();
expected.put("bar", "baz");
expected.put("foo", Collections.singletonMap("baz", 6));
assertEquals(expected, filtered);
// exclude on wildcard
include = new CharacterRunAutomaton(Operations.minus(
Automata.makeAnyString(), Automatons.patterns("foo.*"),
Operations.DEFAULT_MAX_DETERMINIZED_STATES));
filtered = FieldSubsetReader.filter(map, include, 0);
expected = Collections.singletonMap("bar", "baz");
assertEquals(expected, filtered);
// include on inner array // include on inner array
map = new HashMap<>(); map = new HashMap<>();
List<Object> subArray = new ArrayList<>(); List<Object> subArray = new ArrayList<>();
@ -673,7 +685,7 @@ public class FieldSubsetReaderTests extends ESTestCase {
subMap.put("baz", "foo"); subMap.put("baz", "foo");
subArray.add(subMap); subArray.add(subMap);
subArray.add(12); subArray.add(12);
map.put("foo", subMap); map.put("foo", subArray);
include = new CharacterRunAutomaton(Automatons.patterns("foo.bar")); include = new CharacterRunAutomaton(Automatons.patterns("foo.bar"));
filtered = FieldSubsetReader.filter(map, include, 0); filtered = FieldSubsetReader.filter(map, include, 0);
@ -682,7 +694,47 @@ public class FieldSubsetReaderTests extends ESTestCase {
subMap = new HashMap<>(); subMap = new HashMap<>();
subMap.put("bar", 42); subMap.put("bar", 42);
subArray.add(subMap); subArray.add(subMap);
expected.put("foo", subMap); expected.put("foo", subArray);
assertEquals(expected, filtered);
// include on inner array 2
include = new CharacterRunAutomaton(Automatons.patterns("foo"));
filtered = FieldSubsetReader.filter(map, include, 0);
expected = new HashMap<>();
subArray = new ArrayList<>();
subArray.add(12);
expected.put("foo", subArray);
assertEquals(expected, filtered);
// exclude on inner array
include = new CharacterRunAutomaton(Operations.minus(
Automata.makeAnyString(), Automatons.patterns("foo.baz"),
Operations.DEFAULT_MAX_DETERMINIZED_STATES));
filtered = FieldSubsetReader.filter(map, include, 0);
expected = new HashMap<>();
subArray = new ArrayList<>();
subMap = new HashMap<>();
subMap.put("bar", 42);
subArray.add(subMap);
subArray.add(12);
expected.put("foo", subArray);
assertEquals(expected, filtered);
// exclude on inner array 2
include = new CharacterRunAutomaton(Operations.minus(
Automata.makeAnyString(), Automatons.patterns("foo"),
Operations.DEFAULT_MAX_DETERMINIZED_STATES));
filtered = FieldSubsetReader.filter(map, include, 0);
expected = new HashMap<>();
subArray = new ArrayList<>();
subMap = new HashMap<>();
subMap.put("bar", 42);
subMap.put("baz", "foo");
subArray.add(subMap);
expected.put("foo", subArray);
assertEquals(expected, filtered); assertEquals(expected, filtered);
} }