diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/ReservedRoleMappings.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/ReservedRoleMappings.java index e2a92b75762a6..8db5f5ab4c1af 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/ReservedRoleMappings.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/ReservedRoleMappings.java @@ -9,10 +9,10 @@ import org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping; -import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; public class ReservedRoleMappings { private final ClusterStateRoleMapper clusterStateRoleMapper; @@ -26,14 +26,17 @@ public List combineWithReserved(List reservedNames = reservedRoleMappings.stream().map(ExpressionRoleMapping::getName).collect(Collectors.toSet()); - final List filteredNativeRoleMappings = roleMappings.stream() - .filter(roleMapping -> false == reservedNames.contains(roleMapping.getName())) - .toList(); - // TODO optimize - final List combined = new ArrayList<>(reservedRoleMappings); - combined.addAll(filteredNativeRoleMappings); - return List.copyOf(combined); + if (roleMappings.isEmpty()) { + return List.copyOf(reservedRoleMappings); + } + final Map combinedMappings = new LinkedHashMap<>(); + for (ExpressionRoleMapping mapping : reservedRoleMappings) { + combinedMappings.put(mapping.getName(), mapping); + } + for (ExpressionRoleMapping mapping : roleMappings) { + combinedMappings.putIfAbsent(mapping.getName(), mapping); + } + return List.copyOf(combinedMappings.values()); } public boolean isReserved(String roleMappingName) {