Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 0758D200AE8 for ; Tue, 3 May 2016 12:26:40 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 061DA1609F4; Tue, 3 May 2016 12:26:40 +0200 (CEST) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 265C91609F3 for ; Tue, 3 May 2016 12:26:39 +0200 (CEST) Received: (qmail 47573 invoked by uid 500); 3 May 2016 10:26:38 -0000 Mailing-List: contact commits-help@lucene.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@lucene.apache.org Delivered-To: mailing list commits@lucene.apache.org Received: (qmail 47555 invoked by uid 99); 3 May 2016 10:26:38 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 03 May 2016 10:26:38 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 3299DDFBDE; Tue, 3 May 2016 10:26:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: noble@apache.org To: commits@lucene.apache.org Message-Id: <9b0b184f7456409ea096c9bd885a7b23@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: lucene-solr:master: SOLR-9049: RuleBasedAuthorizationPlugin supports regex in param values eg: "command" : "REGEX:(i?)create" Date: Tue, 3 May 2016 10:26:38 +0000 (UTC) archived-at: Tue, 03 May 2016 10:26:40 -0000 Repository: lucene-solr Updated Branches: refs/heads/master 2fe824fd6 -> cf16f5d13 SOLR-9049: RuleBasedAuthorizationPlugin supports regex in param values eg: "command" : "REGEX:(i?)create" Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/cf16f5d1 Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/cf16f5d1 Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/cf16f5d1 Branch: refs/heads/master Commit: cf16f5d13d41f61a748e6376c85eb4941cc4a293 Parents: 2fe824f Author: Noble Paul Authored: Tue May 3 15:56:25 2016 +0530 Committer: Noble Paul Committed: Tue May 3 15:56:25 2016 +0530 ---------------------------------------------------------------------- solr/CHANGES.txt | 2 + .../org/apache/solr/security/Permission.java | 42 ++++++++++++++- .../security/RuleBasedAuthorizationPlugin.java | 11 ++-- .../TestRuleBasedAuthorizationPlugin.java | 54 ++++++++++++++++++++ 4 files changed, 101 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cf16f5d1/solr/CHANGES.txt ---------------------------------------------------------------------- diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 994203e..75cba3d 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -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 ---------------------- http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cf16f5d1/solr/core/src/java/org/apache/solr/security/Permission.java ---------------------------------------------------------------------- diff --git a/solr/core/src/java/org/apache/solr/security/Permission.java b/solr/core/src/java/org/apache/solr/security/Permission.java index 2ec1fcf..3ebf283 100644 --- a/solr/core/src/java/org/apache/solr/security/Permission.java +++ b/solr/core/src/java/org/apache/solr/security/Permission.java @@ -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 path, role, collections, method; - Map params; + Map> 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) m.get("params"); + Map paramRules = (Map) m.get("params"); + if (paramRules != null) { + p.params = new LinkedHashMap<>(); + for (Map.Entry e : paramRules.entrySet()) { + if (e.getValue() == null) { + p.params.put(e.getKey(), (String[] val) -> val == null); + } else { + List 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; } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cf16f5d1/solr/core/src/java/org/apache/solr/security/RuleBasedAuthorizationPlugin.java ---------------------------------------------------------------------- diff --git a/solr/core/src/java/org/apache/solr/security/RuleBasedAuthorizationPlugin.java b/solr/core/src/java/org/apache/solr/security/RuleBasedAuthorizationPlugin.java index 3145113..9f6d4b8 100644 --- a/solr/core/src/java/org/apache/solr/security/RuleBasedAuthorizationPlugin.java +++ b/solr/core/src/java/org/apache/solr/security/RuleBasedAuthorizationPlugin.java @@ -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 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> e : permission.params.entrySet()) { + String[] paramVal = context.getParams().getParams(e.getKey()); + if(!e.getValue().apply(paramVal)) continue loopPermissions; } } } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cf16f5d1/solr/core/src/test/org/apache/solr/security/TestRuleBasedAuthorizationPlugin.java ---------------------------------------------------------------------- diff --git a/solr/core/src/test/org/apache/solr/security/TestRuleBasedAuthorizationPlugin.java b/solr/core/src/test/org/apache/solr/security/TestRuleBasedAuthorizationPlugin.java index 628b4a8..0f70d73 100644 --- a/solr/core/src/test/org/apache/solr/security/TestRuleBasedAuthorizationPlugin.java +++ b/solr/core/src/test/org/apache/solr/security/TestRuleBasedAuthorizationPlugin.java @@ -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 {