diff --git a/src/main/java/org/opensearch/security/privileges/UserAttributes.java b/src/main/java/org/opensearch/security/privileges/UserAttributes.java new file mode 100644 index 0000000000..e138c5f621 --- /dev/null +++ b/src/main/java/org/opensearch/security/privileges/UserAttributes.java @@ -0,0 +1,69 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ +package org.opensearch.security.privileges; + +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Joiner; +import com.google.common.collect.Iterables; + +import org.opensearch.security.user.User; + +/** + * Support for interpolating user attributes used in index patterns and DLS queries. + * + * This code was moved over from ConfigModelV7. + */ +public class UserAttributes { + public static String replaceProperties(String orig, User user) { + + if (user == null || orig == null) { + return orig; + } + + orig = orig.replace("${user.name}", user.getName()).replace("${user_name}", user.getName()); + orig = replaceRoles(orig, user); + orig = replaceSecurityRoles(orig, user); + for (Map.Entry entry : user.getCustomAttributesMap().entrySet()) { + if (entry == null || entry.getKey() == null || entry.getValue() == null) { + continue; + } + orig = orig.replace("${" + entry.getKey() + "}", entry.getValue()); + orig = orig.replace("${" + entry.getKey().replace('.', '_') + "}", entry.getValue()); + } + return orig; + } + + private static String replaceRoles(final String orig, final User user) { + String retVal = orig; + if (orig.contains("${user.roles}") || orig.contains("${user_roles}")) { + final String commaSeparatedRoles = toQuotedCommaSeparatedString(user.getRoles()); + retVal = orig.replace("${user.roles}", commaSeparatedRoles).replace("${user_roles}", commaSeparatedRoles); + } + return retVal; + } + + private static String replaceSecurityRoles(final String orig, final User user) { + String retVal = orig; + if (orig.contains("${user.securityRoles}") || orig.contains("${user_securityRoles}")) { + final String commaSeparatedRoles = toQuotedCommaSeparatedString(user.getSecurityRoles()); + retVal = orig.replace("${user.securityRoles}", commaSeparatedRoles).replace("${user_securityRoles}", commaSeparatedRoles); + } + return retVal; + } + + private static String toQuotedCommaSeparatedString(final Set roles) { + return Joiner.on(',').join(Iterables.transform(roles, s -> { + return new StringBuilder(s.length() + 2).append('"').append(s).append('"').toString(); + })); + } +} diff --git a/src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java b/src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java index 52e8d96462..39a0354d5c 100644 --- a/src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java +++ b/src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java @@ -37,10 +37,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import com.google.common.base.Joiner; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; import com.google.common.collect.MultimapBuilder.SetMultimapBuilder; import com.google.common.collect.SetMultimap; @@ -57,6 +55,7 @@ import org.opensearch.common.util.set.Sets; import org.opensearch.core.common.transport.TransportAddress; import org.opensearch.core.xcontent.NamedXContentRegistry; +import org.opensearch.security.privileges.UserAttributes; import org.opensearch.security.resolver.IndexResolverReplacer.Resolved; import org.opensearch.security.securityconf.impl.SecurityDynamicConfiguration; import org.opensearch.security.securityconf.impl.v7.ActionGroupsV7; @@ -832,7 +831,7 @@ public String toString() { } public String getUnresolvedIndexPattern(User user) { - return replaceProperties(indexPattern, user); + return UserAttributes.replaceProperties(indexPattern, user); } /** Finds the indices accessible to the user and resolves them to concrete names */ @@ -894,7 +893,7 @@ public Set getResolvedIndexPattern( } public String getDlsQuery(User user) { - return replaceProperties(dlsQuery, user); + return UserAttributes.replaceProperties(dlsQuery, user); } public boolean hasDlsQuery() { @@ -1039,49 +1038,6 @@ public String toString() { } } - private static String replaceProperties(String orig, User user) { - - if (user == null || orig == null) { - return orig; - } - - orig = orig.replace("${user.name}", user.getName()).replace("${user_name}", user.getName()); - orig = replaceRoles(orig, user); - orig = replaceSecurityRoles(orig, user); - for (Entry entry : user.getCustomAttributesMap().entrySet()) { - if (entry == null || entry.getKey() == null || entry.getValue() == null) { - continue; - } - orig = orig.replace("${" + entry.getKey() + "}", entry.getValue()); - orig = orig.replace("${" + entry.getKey().replace('.', '_') + "}", entry.getValue()); - } - return orig; - } - - private static String replaceRoles(final String orig, final User user) { - String retVal = orig; - if (orig.contains("${user.roles}") || orig.contains("${user_roles}")) { - final String commaSeparatedRoles = toQuotedCommaSeparatedString(user.getRoles()); - retVal = orig.replace("${user.roles}", commaSeparatedRoles).replace("${user_roles}", commaSeparatedRoles); - } - return retVal; - } - - private static String replaceSecurityRoles(final String orig, final User user) { - String retVal = orig; - if (orig.contains("${user.securityRoles}") || orig.contains("${user_securityRoles}")) { - final String commaSeparatedRoles = toQuotedCommaSeparatedString(user.getSecurityRoles()); - retVal = orig.replace("${user.securityRoles}", commaSeparatedRoles).replace("${user_securityRoles}", commaSeparatedRoles); - } - return retVal; - } - - private static String toQuotedCommaSeparatedString(final Set roles) { - return Joiner.on(',').join(Iterables.transform(roles, s -> { - return new StringBuilder(s.length() + 2).append('"').append(s).append('"').toString(); - })); - } - private static final class IndexMatcherAndPermissions { private WildcardMatcher matcher; private WildcardMatcher perms; @@ -1234,7 +1190,7 @@ public Map mapTenants(final User user, Set roles) { // replaceProperties for tenant name because // at this point e.getValue().v1() can be in this form : "${attr.[internal|jwt|proxy|ldap].*}" // let's substitute it with the eventual value of the user's attribute - final String tenant = replaceProperties(e.getValue().v1(), user); + final String tenant = UserAttributes.replaceProperties(e.getValue().v1(), user); final boolean rw = e.getValue().v2(); if (rw || !result.containsKey(tenant)) { // RW outperforms RO