SOLR-9049: RuleBasedAuthorizationPlugin supports regex in param values eg: "command" : "REGEX:(i?)create"

This commit is contained in:
Noble Paul 2016-05-03 15:56:25 +05:30
parent 72ce1faecd
commit aa6ba7f3be
4 changed files with 101 additions and 8 deletions

View File

@ -93,6 +93,8 @@ New Features
* SOLR-5750: Add /admin/collections?action=BACKUP and RESTORE assuming access to a shared file system. * SOLR-5750: Add /admin/collections?action=BACKUP and RESTORE assuming access to a shared file system.
(Varun Thacker, David Smiley) (Varun Thacker, David Smiley)
* SOLR-9049: RuleBasedAuthorizationPlugin supports regex in param values eg: "command" : "REGEX:(i?)create" (noble)
Bug Fixes Bug Fixes
---------------------- ----------------------

View File

@ -3,15 +3,23 @@ package org.apache.solr.security;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.Pair;
import static java.util.Collections.singleton; import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.apache.solr.common.params.CommonParams.NAME; import static org.apache.solr.common.params.CommonParams.NAME;
/* /*
@ -35,7 +43,7 @@ import static org.apache.solr.common.params.CommonParams.NAME;
class Permission { class Permission {
String name; String name;
Set<String> path, role, collections, method; Set<String> path, role, collections, method;
Map<String, Object> params; Map<String, Function<String[], Boolean>> params;
PermissionNameProvider.Name wellknownName; PermissionNameProvider.Name wellknownName;
private Permission() { private Permission() {
@ -63,7 +71,37 @@ class Permission {
p.path = readSetSmart(name, m, "path"); p.path = readSetSmart(name, m, "path");
p.collections = readSetSmart(name, m, "collection"); p.collections = readSetSmart(name, m, "collection");
p.method = readSetSmart(name, m, "method"); p.method = readSetSmart(name, m, "method");
p.params = (Map<String, Object>) m.get("params"); Map<String, Object> paramRules = (Map<String, Object>) m.get("params");
if (paramRules != null) {
p.params = new LinkedHashMap<>();
for (Map.Entry<String, Object> e : paramRules.entrySet()) {
if (e.getValue() == null) {
p.params.put(e.getKey(), (String[] val) -> val == null);
} else {
List<String> patternStrs = e.getValue() instanceof List ?
(List) e.getValue() :
singletonList(e.getValue().toString());
List patterns = patternStrs.stream()
.map(it -> it.startsWith("REGEX:") ?
Pattern.compile(String.valueOf(it.substring("REGEX:".length())))
: it)
.collect(Collectors.toList());
p.params.put(e.getKey(), val -> {
if (val == null) return false;
for (Object pattern : patterns) {
for (String s : val) {
if (pattern instanceof String) {
if (pattern.equals(s)) return true;
} else if (pattern instanceof Pattern) {
if (((Pattern) pattern).matcher(s).find()) return true;
}
}
}
return false;
});
}
}
}
return p; return p;
} }

View File

@ -26,12 +26,14 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import org.apache.solr.util.CommandOperation; import org.apache.solr.util.CommandOperation;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.emptyIterator;
import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableMap;
import static java.util.function.Function.identity; import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toMap;
@ -129,12 +131,9 @@ public class RuleBasedAuthorizationPlugin implements AuthorizationPlugin, Config
continue; continue;
} }
if (permission.params != null) { if (permission.params != null) {
for (Map.Entry<String, Object> e : permission.params.entrySet()) { for (Map.Entry<String, Function<String[], Boolean>> e : permission.params.entrySet()) {
String paramVal = context.getParams().get(e.getKey()); String[] paramVal = context.getParams().getParams(e.getKey());
Object val = e.getValue(); if(!e.getValue().apply(paramVal)) continue loopPermissions;
if (val instanceof List) {
if (!((List) val).contains(paramVal)) continue loopPermissions;
} else if (!Objects.equals(val, paramVal)) continue loopPermissions;
} }
} }
} }

View File

@ -19,6 +19,7 @@ package org.apache.solr.security;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.security.Principal; import java.security.Principal;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
@ -31,6 +32,7 @@ import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.params.MapSolrParams; import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.Utils; import org.apache.solr.common.util.Utils;
import org.apache.solr.handler.DumpRequestHandler;
import org.apache.solr.handler.ReplicationHandler; import org.apache.solr.handler.ReplicationHandler;
import org.apache.solr.handler.SchemaHandler; import org.apache.solr.handler.SchemaHandler;
import org.apache.solr.handler.UpdateRequestHandler; import org.apache.solr.handler.UpdateRequestHandler;
@ -251,6 +253,58 @@ public class TestRuleBasedAuthorizationPlugin extends SolrTestCaseJ4 {
"params", new MapSolrParams(singletonMap("action", "CREATE"))) "params", new MapSolrParams(singletonMap("action", "CREATE")))
,STATUS_OK ); ,STATUS_OK );
rules = (Map) Utils.fromJSONString(permissions);
List permissions = (List) rules.get("permissions");
permissions.remove(permissions.size() -1);//remove the 'all' permission
permissions.add(makeMap("name", "test-params", "role", "admin", "path", "/x", "params",
makeMap("key", Arrays.asList("REGEX:(?i)val1", "VAL2"))));
this.permissions = Utils.toJSONString(rules);
checkRules(makeMap("resource", "/x",
"userPrincipal", null,
"requestType", RequestType.UNKNOWN,
"collectionRequests", "go",
"handler", new DumpRequestHandler(),
"params", new MapSolrParams(singletonMap("key", "VAL1")))
, PROMPT_FOR_CREDENTIALS);
checkRules(makeMap("resource", "/x",
"userPrincipal", null,
"requestType", RequestType.UNKNOWN,
"collectionRequests", "go",
"handler", new DumpRequestHandler(),
"params", new MapSolrParams(singletonMap("key", "Val1")))
, PROMPT_FOR_CREDENTIALS);
checkRules(makeMap("resource", "/x",
"userPrincipal", null,
"requestType", RequestType.UNKNOWN,
"collectionRequests", "go",
"handler", new DumpRequestHandler(),
"params", new MapSolrParams(singletonMap("key", "Val1")))
, PROMPT_FOR_CREDENTIALS);
checkRules(makeMap("resource", "/x",
"userPrincipal", "joe",
"requestType", RequestType.UNKNOWN,
"collectionRequests", "go",
"handler", new DumpRequestHandler(),
"params", new MapSolrParams(singletonMap("key", "Val1")))
, FORBIDDEN);
checkRules(makeMap("resource", "/x",
"userPrincipal", "joe",
"requestType", RequestType.UNKNOWN,
"collectionRequests", "go",
"handler", new DumpRequestHandler(),
"params", new MapSolrParams(singletonMap("key", "Val2")))
, STATUS_OK);
checkRules(makeMap("resource", "/x",
"userPrincipal", "joe",
"requestType", RequestType.UNKNOWN,
"collectionRequests", "go",
"handler", new DumpRequestHandler(),
"params", new MapSolrParams(singletonMap("key", "VAL2")))
, FORBIDDEN);
} }
public void testEditRules() throws IOException { public void testEditRules() throws IOException {