src/main/java/org/opensearch/security/securityconf/ConfigModelV6.java [266:483]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            });

            futures.add(future);
        }

        execs.shutdown();
        try {
            execs.awaitTermination(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Thread interrupted (1) while loading roles");
            return null;
        }

        try {
            SecurityRoles _securityRoles = new SecurityRoles(futures.size());
            for (Future<SecurityRole> future : futures) {
                _securityRoles.addSecurityRole(future.get());
            }

            return _securityRoles;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Thread interrupted (2) while loading roles");
            return null;
        } catch (ExecutionException e) {
            log.error("Error while updating roles: {}", e.getCause(), e.getCause());
            throw ExceptionsHelper.convertToOpenSearchException(e);
        }
    }


    //beans

    public static class SecurityRoles implements org.opensearch.security.securityconf.SecurityRoles {

        protected final Logger log = LoggerFactory.getLogger(this.getClass());

        final Set<SecurityRole> roles;

        private SecurityRoles(int roleCount) {
            roles = new HashSet<>(roleCount);
        }

        private SecurityRoles addSecurityRole(SecurityRole securityRole) {
            if (securityRole != null) {
                this.roles.add(securityRole);
            }
            return this;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((roles == null) ? 0 : roles.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            SecurityRoles other = (SecurityRoles) obj;
            if (roles == null) {
                if (other.roles != null)
                    return false;
            } else if (!roles.equals(other.roles))
                return false;
            return true;
        }

        @Override
        public String toString() {
            return "roles=" + roles;
        }

        public Set<SecurityRole> getRoles() {
            return Collections.unmodifiableSet(roles);
        }
        public Set<String> getRoleNames() {
            return getRoles().stream().map(r -> r.getName()).collect(Collectors.toSet());
        }
        
        public SecurityRoles filter(Set<String> keep) {
            final SecurityRoles retVal = new SecurityRoles(roles.size());
            for (SecurityRole sr : roles) {
                if (keep.contains(sr.getName())) {
                    retVal.addSecurityRole(sr);
                }
            }
            return retVal;
        }

        @Override
        public Map<String, Set<String>> getMaskedFields(User user, IndexNameExpressionResolver resolver, ClusterService cs) {
            final Map<String, Set<String>> maskedFieldsMap = new HashMap<>();

            for (SecurityRole sr : roles) {
                for (IndexPattern ip : sr.getIpatterns()) {
                    final Set<String> maskedFields = ip.getMaskedFields();
                    if (!maskedFields.isEmpty()) {
                        final String indexPattern = ip.getUnresolvedIndexPattern(user);
                        Set<String> concreteIndices = ip.getResolvedIndexPattern(user, resolver, cs);

                        Set<String> currentMaskedFields = maskedFieldsMap.get(indexPattern);
                        if (currentMaskedFields != null) {
                            currentMaskedFields.addAll(maskedFields);
                        } else {
                            maskedFieldsMap.put(indexPattern, new HashSet<>(maskedFields));
                        }

                        for (String concreteIndex : concreteIndices) {
                            currentMaskedFields = maskedFieldsMap.get(concreteIndex);
                            if (currentMaskedFields != null) {
                                currentMaskedFields.addAll(maskedFields);
                            } else {
                                maskedFieldsMap.put(concreteIndex, new HashSet<>(maskedFields));
                            }
                        }
                    }
                }
            }
            return maskedFieldsMap;
        }

        @Override
        public Tuple<Map<String, Set<String>>, Map<String, Set<String>>> getDlsFls(User user, IndexNameExpressionResolver resolver,
                ClusterService cs) {

            final Map<String, Set<String>> dlsQueries = new HashMap<String, Set<String>>();
            final Map<String, Set<String>> flsFields = new HashMap<String, Set<String>>();

            for (SecurityRole sr : roles) {
                for (IndexPattern ip : sr.getIpatterns()) {
                    final Set<String> fls = ip.getFls();
                    final String dls = ip.getDlsQuery(user);
                    final String indexPattern = ip.getUnresolvedIndexPattern(user);
                    Set<String> concreteIndices = new HashSet<>();

                    if ((dls != null && dls.length() > 0) || (fls != null && fls.size() > 0)) {
                        concreteIndices = ip.getResolvedIndexPattern(user, resolver, cs);
                    }

                    if (dls != null && dls.length() > 0) {

                        Set<String> dlsQuery = dlsQueries.get(indexPattern);
                        if (dlsQuery != null) {
                            dlsQuery.add(dls);
                        } else {
                            dlsQueries.put(indexPattern, new HashSet<>(Arrays.asList(dls)));
                        }

                        for (String concreteIndex : concreteIndices) {
                            dlsQuery = dlsQueries.get(concreteIndex);
                            if (dlsQuery != null) {
                                dlsQuery.add(dls);
                            } else {
                                dlsQueries.put(concreteIndex, new HashSet<>(Arrays.asList(dls)));
                            }
                        }

                    }

                    if (fls != null && fls.size() > 0) {

                        Set<String> flsField = flsFields.get(indexPattern);
                        if (flsField != null) {
                            flsField.addAll(fls);
                        } else {
                            flsFields.put(indexPattern, new HashSet<>(fls));
                        }

                        for (String concreteIndex : concreteIndices) {
                            flsField = flsFields.get(concreteIndex);
                            if (flsField != null) {
                                flsField.addAll(fls);
                            } else {
                                flsFields.put(concreteIndex, new HashSet<>(fls));
                            }
                        }
                    }
                }
            }

            return new Tuple<>(dlsQueries, flsFields);

        }

        //opensearchDashboards special only, terms eval
        public Set<String> getAllPermittedIndicesForDashboards(Resolved resolved, User user, String[] actions, IndexNameExpressionResolver resolver, ClusterService cs) {
            Set<String> retVal = new HashSet<>();
            for (SecurityRole sr : roles) {
                retVal.addAll(sr.getAllResolvedPermittedIndices(Resolved._LOCAL_ALL, user, actions, resolver, cs));
                retVal.addAll(resolved.getRemoteIndices());
            }
            return Collections.unmodifiableSet(retVal);
        }

        //dnfof only
        public Set<String> reduce(Resolved resolved, User user, String[] actions, IndexNameExpressionResolver resolver, ClusterService cs) {
            Set<String> retVal = new HashSet<>();
            for (SecurityRole sr : roles) {
                retVal.addAll(sr.getAllResolvedPermittedIndices(resolved, user, actions, resolver, cs));
            }
            if (log.isDebugEnabled()) {
                log.debug("Reduced requested resolved indices {} to permitted indices {}.", resolved, retVal.toString());
            }
            return Collections.unmodifiableSet(retVal);
        }

        //return true on success
        public boolean get(Resolved resolved, User user, String[] actions, IndexNameExpressionResolver resolver, ClusterService cs) {
            for (SecurityRole sr : roles) {
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java [252:470]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            });

            futures.add(future);
        }

        execs.shutdown();
        try {
            execs.awaitTermination(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Thread interrupted (1) while loading roles");
            return null;
        }

        try {
            SecurityRoles _securityRoles = new SecurityRoles(futures.size());
            for (Future<SecurityRole> future : futures) {
                _securityRoles.addSecurityRole(future.get());
            }

            return _securityRoles;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Thread interrupted (2) while loading roles");
            return null;
        } catch (ExecutionException e) {
            log.error("Error while updating roles: {}", e.getCause(), e.getCause());
            throw ExceptionsHelper.convertToOpenSearchException(e);
        }
    }


    //beans

    public static class SecurityRoles implements org.opensearch.security.securityconf.SecurityRoles {

        protected final Logger log = LoggerFactory.getLogger(this.getClass());

        final Set<SecurityRole> roles;

        private SecurityRoles(int roleCount) {
            roles = new HashSet<>(roleCount);
        }

        private SecurityRoles addSecurityRole(SecurityRole securityRole) {
            if (securityRole != null) {
                this.roles.add(securityRole);
            }
            return this;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((roles == null) ? 0 : roles.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            SecurityRoles other = (SecurityRoles) obj;
            if (roles == null) {
                if (other.roles != null)
                    return false;
            } else if (!roles.equals(other.roles))
                return false;
            return true;
        }

        @Override
        public String toString() {
            return "roles=" + roles;
        }

        public Set<SecurityRole> getRoles() {
            return Collections.unmodifiableSet(roles);
        }
        
        public Set<String> getRoleNames() {
            return getRoles().stream().map(r -> r.getName()).collect(Collectors.toSet());
        }

        public SecurityRoles filter(Set<String> keep) {
            final SecurityRoles retVal = new SecurityRoles(roles.size());
            for (SecurityRole sr : roles) {
                if (keep.contains(sr.getName())) {
                    retVal.addSecurityRole(sr);
                }
            }
            return retVal;
        }

        @Override
        public Map<String, Set<String>> getMaskedFields(User user, IndexNameExpressionResolver resolver, ClusterService cs) {
            final Map<String, Set<String>> maskedFieldsMap = new HashMap<>();

            for (SecurityRole sr : roles) {
                for (IndexPattern ip : sr.getIpatterns()) {
                    final Set<String> maskedFields = ip.getMaskedFields();
                    if (!maskedFields.isEmpty()) {
                        final String indexPattern = ip.getUnresolvedIndexPattern(user);
                        Set<String> concreteIndices = ip.getResolvedIndexPattern(user, resolver, cs);

                        Set<String> currentMaskedFields = maskedFieldsMap.get(indexPattern);
                        if (currentMaskedFields != null) {
                            currentMaskedFields.addAll(maskedFields);
                        } else {
                            maskedFieldsMap.put(indexPattern, new HashSet<>(maskedFields));
                        }

                        for (String concreteIndex : concreteIndices) {
                            currentMaskedFields = maskedFieldsMap.get(concreteIndex);
                            if (currentMaskedFields != null) {
                                currentMaskedFields.addAll(maskedFields);
                            } else {
                                maskedFieldsMap.put(concreteIndex, new HashSet<>(maskedFields));
                            }
                        }
                    }
                }
            }
            return maskedFieldsMap;
        }

        @Override
        public Tuple<Map<String, Set<String>>, Map<String, Set<String>>> getDlsFls(User user, IndexNameExpressionResolver resolver,
                ClusterService cs) {

            final Map<String, Set<String>> dlsQueries = new HashMap<String, Set<String>>();
            final Map<String, Set<String>> flsFields = new HashMap<String, Set<String>>();

            for (SecurityRole sr : roles) {
                for (IndexPattern ip : sr.getIpatterns()) {
                    final Set<String> fls = ip.getFls();
                    final String dls = ip.getDlsQuery(user);
                    final String indexPattern = ip.getUnresolvedIndexPattern(user);
                    Set<String> concreteIndices = new HashSet<>();

                    if ((dls != null && dls.length() > 0) || (fls != null && fls.size() > 0)) {
                        concreteIndices = ip.getResolvedIndexPattern(user, resolver, cs);
                    }

                    if (dls != null && dls.length() > 0) {

                        Set<String> dlsQuery = dlsQueries.get(indexPattern);
                        if (dlsQuery != null) {
                            dlsQuery.add(dls);
                        } else {
                            dlsQueries.put(indexPattern, new HashSet<>(Arrays.asList(dls)));
                        }

                        for (String concreteIndex : concreteIndices) {
                            dlsQuery = dlsQueries.get(concreteIndex);
                            if (dlsQuery != null) {
                                dlsQuery.add(dls);
                            } else {
                                dlsQueries.put(concreteIndex, new HashSet<>(Arrays.asList(dls)));
                            }
                        }

                    }

                    if (fls != null && fls.size() > 0) {

                        Set<String> flsField = flsFields.get(indexPattern);
                        if (flsField != null) {
                            flsField.addAll(fls);
                        } else {
                            flsFields.put(indexPattern, new HashSet<>(fls));
                        }

                        for (String concreteIndex : concreteIndices) {
                            flsField = flsFields.get(concreteIndex);
                            if (flsField != null) {
                                flsField.addAll(fls);
                            } else {
                                flsFields.put(concreteIndex, new HashSet<>(fls));
                            }
                        }
                    }
                }
            }

            return new Tuple<>(dlsQueries, flsFields);

        }

      //opensearchDashboards special only, terms eval
        public Set<String> getAllPermittedIndicesForDashboards(Resolved resolved, User user, String[] actions, IndexNameExpressionResolver resolver, ClusterService cs) {
            Set<String> retVal = new HashSet<>();
            for (SecurityRole sr : roles) {
                retVal.addAll(sr.getAllResolvedPermittedIndices(Resolved._LOCAL_ALL, user, actions, resolver, cs));
                retVal.addAll(resolved.getRemoteIndices());
            }
            return Collections.unmodifiableSet(retVal);
        }

        //dnfof only
        public Set<String> reduce(Resolved resolved, User user, String[] actions, IndexNameExpressionResolver resolver, ClusterService cs) {
            Set<String> retVal = new HashSet<>();
            for (SecurityRole sr : roles) {
                retVal.addAll(sr.getAllResolvedPermittedIndices(resolved, user, actions, resolver, cs));
            }
            if (log.isDebugEnabled()) {
                log.debug("Reduced requested resolved indices {} to permitted indices {}.", resolved, retVal.toString());
            }
            return Collections.unmodifiableSet(retVal);
        }

        //return true on success
        public boolean get(Resolved resolved, User user, String[] actions, IndexNameExpressionResolver resolver, ClusterService cs) {
            for (SecurityRole sr : roles) {
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



