2323import org .elasticsearch .common .logging .DeprecationCategory ;
2424import org .elasticsearch .common .logging .DeprecationLogger ;
2525import org .elasticsearch .common .regex .Regex ;
26+ import org .elasticsearch .common .util .CachedSupplier ;
2627import org .elasticsearch .common .util .Maps ;
2728import org .elasticsearch .common .util .set .Sets ;
2829import org .elasticsearch .core .Nullable ;
@@ -324,14 +325,14 @@ public boolean checkResourcePrivileges(
324325 @ Nullable ResourcePrivilegesMap .Builder resourcePrivilegesMapBuilder
325326 ) {
326327 boolean allMatch = true ;
327- Map <Automaton , Automaton > indexGroupAutomatonsForDataSelector = indexGroupAutomatons (
328+ Map <Automaton , List < Automaton > > indexGroupAutomatonsForDataSelector = indexGroupAutomatons (
328329 combineIndexGroups && checkForIndexPatterns .stream ().anyMatch (Automatons ::isLuceneRegex ),
329330 IndexComponentSelector .DATA
330331 );
331332 // optimization: if there are no failures selector privileges in the set of privileges to check, we can skip building
332333 // the automaton map
333334 final boolean containsPrivilegesForFailuresSelector = containsPrivilegesForFailuresSelector (checkForPrivileges );
334- Map <Automaton , Automaton > indexGroupAutomatonsForFailuresSelector = false == containsPrivilegesForFailuresSelector
335+ Map <Automaton , List < Automaton > > indexGroupAutomatonsForFailuresSelector = false == containsPrivilegesForFailuresSelector
335336 ? Map .of ()
336337 : indexGroupAutomatons (
337338 combineIndexGroups && checkForIndexPatterns .stream ().anyMatch (Automatons ::isLuceneRegex ),
@@ -845,43 +846,54 @@ private static boolean containsPrivilegeThatGrantsMappingUpdatesForBwc(Group gro
845846 *
846847 * @param combine combine index groups to allow for checking against regular expressions
847848 *
848- * @return a map of all index and privilege pattern automatons
849+ * @return a map of all privilege to index pattern automatons
849850 */
850- private Map <Automaton , Automaton > indexGroupAutomatons (boolean combine , IndexComponentSelector selector ) {
851+ private Map <Automaton , List < Automaton > > indexGroupAutomatons (boolean combine , IndexComponentSelector selector ) {
851852 // Map of privilege automaton object references (cached by IndexPrivilege::CACHE)
852- Map < Automaton , Automaton > allAutomatons = new HashMap <>();
853+ var privilegeToIndexAutomatons = new HashMap <Automaton , List < Automaton > >();
853854 for (Group group : groups ) {
854855 if (false == group .checkSelector (selector )) {
855856 continue ;
856857 }
857858 Automaton indexAutomaton = group .getIndexMatcherAutomaton ();
858- allAutomatons .compute (
859- group .privilege ().getAutomaton (),
860- (key , value ) -> value == null ? indexAutomaton : Automatons .unionAndMinimize (List .of (value , indexAutomaton ))
861- );
859+
862860 if (combine ) {
861+ privilegeToIndexAutomatons .compute (
862+ group .privilege ().getAutomaton (),
863+ (key , value ) -> value == null
864+ ? List .of (indexAutomaton )
865+ : List .of (Automatons .unionAndMinimize (List .of (value .get (0 ), indexAutomaton )))
866+ );
863867 List <Tuple <Automaton , Automaton >> combinedAutomatons = new ArrayList <>();
864- for (var indexAndPrivilegeAutomatons : allAutomatons .entrySet ()) {
868+ for (var privilegeAndIndexAutomatons : privilegeToIndexAutomatons .entrySet ()) {
865869 Automaton intersectingPrivileges = Operations .intersection (
866- indexAndPrivilegeAutomatons .getKey (),
870+ privilegeAndIndexAutomatons .getKey (),
867871 group .privilege ().getAutomaton ()
868872 );
869873 if (Operations .isEmpty (intersectingPrivileges ) == false ) {
870874 Automaton indexPatternAutomaton = Automatons .unionAndMinimize (
871- List .of (indexAndPrivilegeAutomatons .getValue (), indexAutomaton )
875+ List .of (privilegeAndIndexAutomatons .getValue (). get ( 0 ), indexAutomaton )
872876 );
873877 combinedAutomatons .add (new Tuple <>(intersectingPrivileges , indexPatternAutomaton ));
874878 }
875879 }
876880 combinedAutomatons .forEach (
877- automatons -> allAutomatons .compute (
881+ automatons -> privilegeToIndexAutomatons .compute (
878882 automatons .v1 (),
879- (key , value ) -> value == null ? automatons .v2 () : Automatons .unionAndMinimize (List .of (value , automatons .v2 ()))
883+ (key , value ) -> value == null
884+ ? List .of (automatons .v2 ())
885+ : List .of (Automatons .unionAndMinimize (List .of (value .get (0 ), automatons .v2 ())))
880886 )
881887 );
888+ } else {
889+ privilegeToIndexAutomatons .compute (group .privilege ().getAutomaton (), (k , v ) -> {
890+ var list = v == null ? new ArrayList <Automaton >() : v ;
891+ list .add (group .getIndexMatcherAutomaton ());
892+ return list ;
893+ });
882894 }
883895 }
884- return allAutomatons ;
896+ return privilegeToIndexAutomatons ;
885897 }
886898
887899 private static boolean containsPrivilegesForFailuresSelector (Set <String > checkForPrivileges ) {
@@ -898,21 +910,26 @@ private static boolean containsPrivilegesForFailuresSelector(Set<String> checkFo
898910 }
899911
900912 @ Nullable
901- private static Automaton getIndexPrivilegesAutomaton (Map <Automaton , Automaton > indexGroupAutomatons , Automaton checkIndexAutomaton ) {
913+ private static Automaton getIndexPrivilegesAutomaton (
914+ Map <Automaton , List <Automaton >> indexGroupAutomatons ,
915+ Automaton checkIndexAutomaton
916+ ) {
902917 if (indexGroupAutomatons .isEmpty ()) {
903918 return null ;
904919 }
905920 Automaton allowedPrivilegesAutomaton = null ;
906- for (Map .Entry <Automaton , Automaton > indexAndPrivilegeAutomaton : indexGroupAutomatons .entrySet ()) {
907- Automaton indexNameAutomaton = indexAndPrivilegeAutomaton .getValue ();
908- if (Operations .subsetOf (checkIndexAutomaton , indexNameAutomaton )) {
909- Automaton privilegesAutomaton = indexAndPrivilegeAutomaton .getKey ();
910- if (allowedPrivilegesAutomaton != null ) {
911- allowedPrivilegesAutomaton = Automatons .unionAndMinimize (
912- Arrays .asList (allowedPrivilegesAutomaton , privilegesAutomaton )
913- );
914- } else {
915- allowedPrivilegesAutomaton = privilegesAutomaton ;
921+ for (Map .Entry <Automaton , List <Automaton >> indexAndPrivilegeAutomaton : indexGroupAutomatons .entrySet ()) {
922+ List <Automaton > indexNameAutomatons = indexAndPrivilegeAutomaton .getValue ();
923+ for (var indexNameAutomaton : indexNameAutomatons ) {
924+ if (Operations .subsetOf (checkIndexAutomaton , indexNameAutomaton )) {
925+ Automaton privilegesAutomaton = indexAndPrivilegeAutomaton .getKey ();
926+ if (allowedPrivilegesAutomaton != null ) {
927+ allowedPrivilegesAutomaton = Automatons .unionAndMinimize (
928+ Arrays .asList (allowedPrivilegesAutomaton , privilegesAutomaton )
929+ );
930+ } else {
931+ allowedPrivilegesAutomaton = privilegesAutomaton ;
932+ }
916933 }
917934 }
918935 }
@@ -950,15 +967,13 @@ public Group(
950967 this .selectorPredicate = privilege .getSelectorPredicate ();
951968 this .indices = indices ;
952969 this .allowRestrictedIndices = allowRestrictedIndices ;
953- ConcurrentHashMap <String [], Automaton > indexNameAutomatonMemo = new ConcurrentHashMap <>(1 );
954970 if (allowRestrictedIndices ) {
955971 this .indexNameMatcher = StringMatcher .of (indices );
956- this .indexNameAutomaton = () -> indexNameAutomatonMemo . computeIfAbsent ( indices , k -> Automatons .patterns (indices ));
972+ this .indexNameAutomaton = CachedSupplier . wrap (() -> Automatons .patterns (indices ));
957973 } else {
958974 this .indexNameMatcher = StringMatcher .of (indices ).and (name -> restrictedIndices .isRestricted (name ) == false );
959- this .indexNameAutomaton = () -> indexNameAutomatonMemo .computeIfAbsent (
960- indices ,
961- k -> Automatons .minusAndMinimize (Automatons .patterns (indices ), restrictedIndices .getAutomaton ())
975+ this .indexNameAutomaton = CachedSupplier .wrap (
976+ () -> Automatons .minusAndMinimize (Automatons .patterns (indices ), restrictedIndices .getAutomaton ())
962977 );
963978 }
964979 this .fieldPermissions = Objects .requireNonNull (fieldPermissions );
0 commit comments