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 2fe824fd6e
commit cf16f5d13d
4 changed files with 101 additions and 8 deletions

View File

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

View File

@ -3,15 +3,23 @@ package org.apache.solr.security;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
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.params.CommonParams;
import org.apache.solr.common.util.Pair;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.apache.solr.common.params.CommonParams.NAME;
/*
@ -35,7 +43,7 @@ import static org.apache.solr.common.params.CommonParams.NAME;
class Permission {
String name;
Set<String> path, role, collections, method;
Map<String, Object> params;
Map<String, Function<String[], Boolean>> params;
PermissionNameProvider.Name wellknownName;
private Permission() {
@ -63,7 +71,37 @@ class Permission {
p.path = readSetSmart(name, m, "path");
p.collections = readSetSmart(name, m, "collection");
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;
}

View File

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

View File

@ -19,6 +19,7 @@ package org.apache.solr.security;
import java.io.IOException;
import java.io.StringReader;
import java.security.Principal;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
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.SolrParams;
import org.apache.solr.common.util.Utils;
import org.apache.solr.handler.DumpRequestHandler;
import org.apache.solr.handler.ReplicationHandler;
import org.apache.solr.handler.SchemaHandler;
import org.apache.solr.handler.UpdateRequestHandler;
@ -251,6 +253,58 @@ public class TestRuleBasedAuthorizationPlugin extends SolrTestCaseJ4 {
"params", new MapSolrParams(singletonMap("action", "CREATE")))
,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 {