This commit is contained in:
Karl Wright 2016-05-03 06:46:01 -04:00
commit a492117576
6 changed files with 122 additions and 21 deletions

View File

@ -127,6 +127,9 @@ Other
* LUCENE-7210: Make TestCore*Parser's analyzer choice override-able
(Christine Poerschke, Daniel Collins)
* LUCENE-7263: Make queryparser/xml/CoreParser's SpanQueryBuilderFactory
accessible to deriving classes. (Daniel Collins via Christine Poerschke)
======================= Lucene 6.0.0 =======================
System Requirements

View File

@ -36,6 +36,7 @@ public class CoreParser implements QueryBuilder {
protected Analyzer analyzer;
protected QueryParser parser;
protected QueryBuilderFactory queryFactory;
final protected SpanQueryBuilderFactory spanFactory;
/**
@ -62,6 +63,8 @@ public class CoreParser implements QueryBuilder {
this.parser = parser;
queryFactory = new QueryBuilderFactory();
spanFactory = new SpanQueryBuilderFactory();
queryFactory.addBuilder("TermQuery", new TermQueryBuilder());
queryFactory.addBuilder("TermsQuery", new TermsQueryBuilder(analyzer));
queryFactory.addBuilder("MatchAllDocsQuery", new MatchAllDocsQueryBuilder());
@ -77,34 +80,32 @@ public class CoreParser implements QueryBuilder {
}
queryFactory.addBuilder("ConstantScoreQuery", new ConstantScoreQueryBuilder(queryFactory));
SpanQueryBuilderFactory sqof = new SpanQueryBuilderFactory();
SpanNearBuilder snb = new SpanNearBuilder(sqof);
sqof.addBuilder("SpanNear", snb);
SpanNearBuilder snb = new SpanNearBuilder(spanFactory);
spanFactory.addBuilder("SpanNear", snb);
queryFactory.addBuilder("SpanNear", snb);
BoostingTermBuilder btb = new BoostingTermBuilder();
sqof.addBuilder("BoostingTermQuery", btb);
spanFactory.addBuilder("BoostingTermQuery", btb);
queryFactory.addBuilder("BoostingTermQuery", btb);
SpanTermBuilder snt = new SpanTermBuilder();
sqof.addBuilder("SpanTerm", snt);
spanFactory.addBuilder("SpanTerm", snt);
queryFactory.addBuilder("SpanTerm", snt);
SpanOrBuilder sot = new SpanOrBuilder(sqof);
sqof.addBuilder("SpanOr", sot);
SpanOrBuilder sot = new SpanOrBuilder(spanFactory);
spanFactory.addBuilder("SpanOr", sot);
queryFactory.addBuilder("SpanOr", sot);
SpanOrTermsBuilder sots = new SpanOrTermsBuilder(analyzer);
sqof.addBuilder("SpanOrTerms", sots);
spanFactory.addBuilder("SpanOrTerms", sots);
queryFactory.addBuilder("SpanOrTerms", sots);
SpanFirstBuilder sft = new SpanFirstBuilder(sqof);
sqof.addBuilder("SpanFirst", sft);
SpanFirstBuilder sft = new SpanFirstBuilder(spanFactory);
spanFactory.addBuilder("SpanFirst", sft);
queryFactory.addBuilder("SpanFirst", sft);
SpanNotBuilder snot = new SpanNotBuilder(sqof);
sqof.addBuilder("SpanNot", snot);
SpanNotBuilder snot = new SpanNotBuilder(spanFactory);
spanFactory.addBuilder("SpanNot", snot);
queryFactory.addBuilder("SpanNot", snot);
}
@ -116,6 +117,10 @@ public class CoreParser implements QueryBuilder {
queryFactory.addBuilder(nodeName, builder);
}
public void addSpanBuilder(String nodeName, SpanQueryBuilder builder) {
spanFactory.addBuilder(nodeName, builder);
}
static Document parseXML(InputStream pXmlFile) throws ParserException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;

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 {