diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/FieldSubsetReader.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/FieldSubsetReader.java index 848587068b2..746e3ea6f7a 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/FieldSubsetReader.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/FieldSubsetReader.java @@ -160,9 +160,7 @@ public final class FieldSubsetReader extends FilterLeafReader { Object value = entry.getValue(); - if (includeAutomaton.isAccept(state)) { - filtered.put(key, value); - } else if (value instanceof Map) { + if (value instanceof Map) { state = includeAutomaton.step(state, '.'); if (state == -1) { continue; @@ -179,6 +177,8 @@ public final class FieldSubsetReader extends FilterLeafReader { if (filteredValue.isEmpty() == false) { filtered.put(key, filteredValue); } + } else if (includeAutomaton.isAccept(state)) { + filtered.put(key, value); } } return filtered; @@ -202,6 +202,8 @@ public final class FieldSubsetReader extends FilterLeafReader { if (filteredValue.isEmpty() == false) { filtered.add(filteredValue); } + } else if (includeAutomaton.isAccept(initialState)) { + filtered.add(value); } } return filtered; diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/FieldSubsetReaderTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/FieldSubsetReaderTests.java index 64c45db2be3..1b9d0957e26 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/FieldSubsetReaderTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/FieldSubsetReaderTests.java @@ -41,6 +41,7 @@ import org.apache.lucene.util.TestUtil; import org.apache.lucene.util.automaton.Automata; import org.apache.lucene.util.automaton.Automaton; 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.SourceFieldMapper; import org.elasticsearch.test.ESTestCase; @@ -625,7 +626,7 @@ public class FieldSubsetReaderTests extends ESTestCase { assertEquals(expected, filtered); - // include on object + // include on inner wildcard map = new HashMap<>(); Map subMap = new HashMap<>(); subMap.put("bar", 42); @@ -633,14 +634,6 @@ public class FieldSubsetReaderTests extends ESTestCase { map.put("foo", subMap); 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.*")); filtered = FieldSubsetReader.filter(map, include, 0); expected = new HashMap<>(); @@ -652,7 +645,6 @@ public class FieldSubsetReaderTests extends ESTestCase { include = new CharacterRunAutomaton(Automatons.patterns("*.bar")); filtered = FieldSubsetReader.filter(map, include, 0); expected = new HashMap<>(); - expected = new HashMap<>(); subMap = new HashMap<>(); subMap.put("bar", 42); expected.put("foo", subMap); @@ -665,6 +657,26 @@ public class FieldSubsetReaderTests extends ESTestCase { 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 map = new HashMap<>(); List subArray = new ArrayList<>(); @@ -673,7 +685,7 @@ public class FieldSubsetReaderTests extends ESTestCase { subMap.put("baz", "foo"); subArray.add(subMap); subArray.add(12); - map.put("foo", subMap); + map.put("foo", subArray); include = new CharacterRunAutomaton(Automatons.patterns("foo.bar")); filtered = FieldSubsetReader.filter(map, include, 0); @@ -682,7 +694,47 @@ public class FieldSubsetReaderTests extends ESTestCase { subMap = new HashMap<>(); subMap.put("bar", 42); 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); }