diff --git a/DISCLAIMER.txt b/DISCLAIMER.txt
index 4d8e175ece..b3bc2048ed 100644
--- a/DISCLAIMER.txt
+++ b/DISCLAIMER.txt
@@ -1,15 +1,6 @@
-Apache Ranger is an effort undergoing incubation at the Apache Software
-Foundation (ASF), sponsored by the Apache Incubator PMC.
+Apache Ranger is a Top Level Project (TLP) at the Apache Software Foundation (ASF).
-Incubation is required of all newly accepted projects until a further review
-indicates that the infrastructure, communications, and decision making process
-have stabilized in a manner consistent with other successful ASF projects.
+This product includes software developed at The Apache Software
+Foundation (http://www.apache.org/).
-While incubation status is not necessarily a reflection of the completeness
-or stability of the code, it does indicate that the project has yet to be
-fully endorsed by the ASF.
-
-For more information about the incubation status of the Apache Ranger project you
-can go to the following page:
-
-http://ranger.incubator.apache.org
+http://ranger.apache.org
diff --git a/LICENSE.txt b/LICENSE.txt
index 2877b1ff56..7aa4bf4e63 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -214,38 +214,39 @@ licenses.
The Apache Ranger project bundles the following files under the MIT License:
-This product includes jQuery (http://jquery.org - MIT license), Copyright © 2014, John Resig.
-This product includes jQuery UI (http://jqueryui.com - MIT license), Copyright © 2013 jQuery Foundation.
-This product includes Backbone (http://backbonejs.org - MIT license), Copyright © 2010-2014 Jeremy Ashkenas, DocumentCloud.
-This product includes underscore (http:underscorejs.org - MIT license), Copyright © 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors.
-This product includes Backbone.Marionette (http://marionettejs.com/ - MIT license).
-This product includes Backbone.Wreqr (http://marionettejs.com/ - MIT license) Copyright ©,2012 Derick Bailey, Muted Solutions, LLC.
-This product includes Backbone.BabySitter (http://marionettejs.com/ - MIT license), Copyright ©2013 Derick Bailey, Muted Solutions, LLC.
-This product includes Backbone fetch cache (https://github.com/mrappleton/backbone-fetch-cache - MIT license), Copyright © 2012-2013 Andrew Appleton.
-This product includes Backbone-forms (https://github.com/powmedia/backbone-forms - MIT license), Copyright © 2013 Charles Davison.
-This product includes Backbone localStorage Adapter v1.1.7 (http://documentup.com/jeromegn/backbone.localStorage - MIT license), Copyright © 2010 Jerome Gravel-Niquet.
-This product includes Backbone.BootstrapModal (https://github.com/powmedia/backbone.bootstrap-modal - MIT license), Copyright © 2013 Charles Davison.
-This product includes X-editable - v1.5.0 (http://vitalets.github.io/x-editable/ - MIT license), Copyright © 2013 Vitaliy Potapov;
-This product includes backgrid 0.3.5 (http://backgridjs.com/ - MIT license), Copyright © 2014 Jimmy Yuen Ho Wong and contributors.
-This product includes backgrid-paginator (http://github.com/wyuenho/backgrid - MIT license), Copyright © 2013 Jimmy Yuen Ho Wong and contributors. This product includes backgrid-filter (http://github.com/wyuenho/backgrid - MIT license), Copyright © 2013 Jimmy Yuen Ho Wong and contributors.
-This product includes backbone-pageable 1.3.2 (http://github.com/wyuenho/backbone-pageable - MIT license), Copyright © 2013 Jimmy Yuen Ho Wong.
-This product includes jQuery Cookie Plugin v1.4.0 (https://github.com/carhartl/jquery-cookie - MIT license), Copyright 2013 Klaus Hartl
-This product includes jQuery Toggles v2.0.4 (http://simontabor.com/labs/toggles - MIT license), Copyright 2013 Simon Tabor.
-This product includes jQuery UI Tag-it! (http://aehlke.github.com/tag-it/ - MIT license), Copyright 2011, Levy Carneiro Jr.
-This product includes bootbox.js v3.3.0 (http://bootboxjs.com/ - MIT license), Copyright © 2011-2014 by Nick Payne.
-This product includes moment.js (http://moment.js - MIT license), Copyright © 2011-2014 Tim Wood, Iskren Chernev, Moment.js contributors.
-This product includes Globalize (http://github.com/jquery/globalize - MIT license), Copyright Software Freedom Conservancy, Inc. Globalize license applies to all files under globalize including globalize/generator.
-This product includes RequireJS 2.1.8 (https://github.com/requirejs/requirejs - MIT licensed), Copyright jQuery Foundation and other contributors.
-This product includes Handlebars.js (http://handlebarsjs.com/ - MIT license), Copyright © 2011-2014 by Yehuda Katz.
-This product includes Font Awesome 3.2.1 (http://fontawesome.io/ - MIT license) by Dave Gandy
-This product includes Qunit(https://qunitjs.com/ - MIT license) Copyright (c) 2011 John Resig, Jörn Zaefferer
-This product includes jQuery Migrate-v1.1.1 (https://plugins.jquery.com/migrate/ - MIT license) Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
+This product includes jQuery (http://jquery.org ), Copyright © 2014, John Resig.
+This product includes jQuery UI (http://jqueryui.com ), Copyright © 2013 jQuery Foundation.
+This product includes Backbone (http://backbonejs.org ), Copyright © 2010-2014 Jeremy Ashkenas, DocumentCloud.
+This product includes underscore (http:underscorejs.org ), Copyright © 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors.
+This product includes Backbone.Marionette (http://marionettejs.com/ ) Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
+This product includes Backbone.Wreqr (http://marionettejs.com/ ) Copyright ©,2012 Derick Bailey, Muted Solutions, LLC.
+This product includes Backbone.BabySitter (http://marionettejs.com/ ), Copyright ©2013 Derick Bailey, Muted Solutions, LLC.
+This product includes Backbone fetch cache (https://github.com/mrappleton/backbone-fetch-cache ), Copyright © 2012-2013 Andrew Appleton.
+This product includes Backbone-forms (https://github.com/powmedia/backbone-forms ), Copyright © 2013 Charles Davison.
+This product includes Backbone localStorage Adapter v1.1.7 (http://documentup.com/jeromegn/backbone.localStorage ), Copyright © 2010 Jerome Gravel-Niquet.
+This product includes Backbone.BootstrapModal (https://github.com/powmedia/backbone.bootstrap-modal ), Copyright © 2013 Charles Davison.
+This product includes X-editable - v1.5.0 (http://vitalets.github.io/x-editable/ ), Copyright © 2013 Vitaliy Potapov;
+This product includes backgrid 0.3.5 (http://backgridjs.com/ ), Copyright © 2014 Jimmy Yuen Ho Wong and contributors.
+This product includes backgrid-paginator (http://github.com/wyuenho/backgrid ), Copyright © 2013 Jimmy Yuen Ho Wong and contributors. This product includes backgrid-filter (http://github.com/wyuenho/backgrid ), Copyright © 2013 Jimmy Yuen Ho Wong and contributors.
+This product includes backbone-pageable 1.3.2 (http://github.com/wyuenho/backbone-pageable ), Copyright © 2013 Jimmy Yuen Ho Wong.
+This product includes jQuery Cookie Plugin v1.4.0 (https://github.com/carhartl/jquery-cookie ), Copyright 2013 Klaus Hartl
+This product includes jQuery Toggles v2.0.4 (http://simontabor.com/labs/toggles ), Copyright 2013 Simon Tabor.
+This product includes jQuery UI Tag-it! (http://aehlke.github.com/tag-it/ ), Copyright 2011, Levy Carneiro Jr.
+This product includes bootbox.js v3.3.0 (http://bootboxjs.com/ ), Copyright © 2011-2014 by Nick Payne.
+This product includes moment.js (http://moment.js ), Copyright © 2011-2014 Tim Wood, Iskren Chernev, Moment.js contributors.
+This product includes Globalize (http://github.com/jquery/globalize ), Copyright Software Freedom Conservancy, Inc. Globalize license applies to all files under globalize including globalize/generator.
+This product includes RequireJS 2.1.8 (https://github.com/requirejs/requirejs ), Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
+This product includes Handlebars.js (http://handlebarsjs.com/ ), Copyright © 2011-2016 by Yehuda Katz.
+This product includes Font Awesome 3.2.1 (http://fontawesome.io/ ) by Dave Gandy
+This product includes Qunit(https://qunitjs.com/ ) Copyright (c) 2011 John Resig, Jörn Zaefferer
+This product includes jQuery Migrate-v1.1.1 (https://plugins.jquery.com/migrate/ ) Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
This product includes bootstrap v2.3.2 (http://getbootstrap.com/ - MIT License) Copyright 2013 Twitter, Inc.
This product includes Block UI v1.1.1 (https://github.com/dreamerslab/jquery.msg/ - MIT License) Copyright 2011, Ben Lin.
-This product includes Sizzle (http://sizzlejs.com/ - MIT license), Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
-This product includes ES5 15.5.4.20 (https://github.com/kriskowal/es5-shim - MIT license), Copyright 2009, 2010 Kristopher Michael Kowal.
+This product includes Sizzle (http://sizzlejs.com/ ), Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
+This product includes ES5 15.5.4.20 (https://github.com/kriskowal/es5-shim ), Copyright 2009, 2010 Kristopher Michael Kowal.
This product includes PURE CSS GUI ICONS 1.0.1(http://nicolasgallagher.com/pure-css-gui-icons/ - Dual licensed under MIT and GNU GPLv2), by Nicolas Gallagher
-This product includes libpam4j 1.8 (https://github.com/kohsuke/libpam4j - MIT license), Copyright Kohsuke Kawaguchi.
+This product includes libpam4j 1.8 (https://github.com/kohsuke/libpam4j ), Copyright Kohsuke Kawaguchi.
+This product bundles VisualSearch.js 0.4.0 (http://documentcloud.github.io/visualsearch/docs/visualsearch.html ), © 2011 Samuel Clay, @samuelclay, DocumentCloud Inc.
@@ -292,49 +293,11 @@ This product includes Require.js Handlebars Plugin (https://github.com/SlexAxton
0. You just DO WHAT THE FUCK YOU WANT TO.
------------------------------------------------------------------------
- VisualSearch License
------------------------------------------------------------------------
-This product includes VisualSearch.js 0.4.0 (http://documentcloud.github.com/visualsearch), © 2011 Samuel Clay, @samuelclay, DocumentCloud Inc.
-
-Copyright (c) 2011 Samuel Clay, @samuelclay, DocumentCloud
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
------------------------------------------------------------------------
- The Apache License 2.0
------------------------------------------------------------------------
-This product includes Bootstrap Datepicker (http://www.eyecon.ro/bootstrap-datepicker - Apache License - 2.0), Copyright 2012 Stefan Petre.
-This product includes bootstrap-transition.js v2.3.2 (http://twbs.github.com/bootstrap/javascript.html#transitions - Apache License - 2.0), Copyright 2013 Twitter, Inc.
-This product includes Select2 3.4.3 (http://ivaynberg.github.io/select2/ - Apache License - 2.0), Copyright 2012 Igor Vaynberg.
-This product includes bootstrap-notify v1.0 (http://goodybag.github.io/bootstrap-notify/ - Apache License - 2.0), Copyright 2012 Goodybag, Inc.
-This product includes Open Sans font (http://www.opensans.com/ - Apache License - 2.0), © 2016 OpenSans.com
-This product includes Jisql (https://bitbucket.org/stdunbar/jisql - Apache License - 2.0), © 2004-2011 Scott Dunbar
-This product includes PasswordComparisonAuthenticator.java in Spring Security (https://github.com/spring-projects/spring-security - Apache License - 2.0), Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
-
-----------------------------------------------------------------------
BSD license
-----------------------------------------------------------------------
This product includes Easing Functions in jQuery UI v1.10.3 (http://www.robertpenner.com/easing - BSD License), Copyright © 2001 by Robert Penner.
-
-Copyright © 2001 Robert Penner
-All rights reserved.
+This product includes Esprima (https://github.com/jquery/esprima - BSD License), Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@@ -354,101 +317,6 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------
- SIL Open Font License (OFL)
------------------------------------------------------------------------
-This product includes Font Awesome 3.2.1 (http://fontawesome.io/ - SIL Open Font License (OFL) licensee) by Dave Gandy
-
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
-
------------------------------------------------------------------------
- Public Domain License
------------------------------------------------------------------------
-This product includes json2.js (https://github.com/douglascrockford/JSON-js - Public Domain license) by Douglas Crockford
-
------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/NOTICE.txt b/NOTICE.txt
index b5841f2f7a..7f6238eae1 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,7 +1,7 @@
Apache Ranger
-Copyright 2014-2016 The Apache Software Foundation
-
-This product includes software developed at The Apache Software
-Foundation (http://www.apache.org/).
-
+Copyright 2014-2017 The Apache Software Foundation
+This product includes software developed at The Apache Software Foundation (http://www.apache.org/).
+his product includes json2.js (https://github.com/douglascrockford/JSON-js - Public Domain license) by Douglas Crockford
+This product includes Font Awesome 3.2.1 (http://fontawesome.io/ - SIL Open Font License (OFL) licensee) by Dave Gandy
+This product includes software developed by Spring Security Project (http://www.springframework.org/security)
diff --git a/agents-audit/pom.xml b/agents-audit/pom.xml
index 40ec34d3b8..13d809d342 100644
--- a/agents-audit/pom.xml
+++ b/agents-audit/pom.xml
@@ -27,7 +27,7 @@
org.apache.ranger
ranger
- 0.6.0
+ 0.6.4-SNAPSHOT
..
diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/destination/SolrAuditDestination.java b/agents-audit/src/main/java/org/apache/ranger/audit/destination/SolrAuditDestination.java
index 46f33a53b6..738c0918a8 100644
--- a/agents-audit/src/main/java/org/apache/ranger/audit/destination/SolrAuditDestination.java
+++ b/agents-audit/src/main/java/org/apache/ranger/audit/destination/SolrAuditDestination.java
@@ -54,7 +54,7 @@ public class SolrAuditDestination extends AuditDestination {
public static final String DEFAULT_COLLECTION_NAME = "ranger_audits";
public static final String PROP_JAVA_SECURITY_AUTH_LOGIN_CONFIG = "java.security.auth.login.config";
- SolrClient solrClient = null;
+ private volatile SolrClient solrClient = null;
public SolrAuditDestination() {
}
@@ -74,77 +74,80 @@ public void stop() {
}
synchronized void connect() {
- if (solrClient == null) {
- if (solrClient == null) {
- String urls = MiscUtil.getStringProperty(props, propPrefix
- + "." + PROP_SOLR_URLS);
- if (urls != null) {
- urls = urls.trim();
- }
- if (urls != null && urls.equalsIgnoreCase("NONE")) {
- urls = null;
- }
-
- List solrURLs = new ArrayList();
- String zkHosts = null;
- solrURLs = MiscUtil.toArray(urls, ",");
- zkHosts = MiscUtil.getStringProperty(props, propPrefix + "."
- + PROP_SOLR_ZK);
- if (zkHosts != null && zkHosts.equalsIgnoreCase("NONE")) {
- zkHosts = null;
- }
-
- String collectionName = MiscUtil.getStringProperty(props,
- propPrefix + "." + PROP_SOLR_COLLECTION);
- if (collectionName == null
- || collectionName.equalsIgnoreCase("none")) {
- collectionName = DEFAULT_COLLECTION_NAME;
- }
-
- LOG.info("Solr zkHosts=" + zkHosts + ", solrURLs=" + urls
- + ", collectionName=" + collectionName);
-
- if (zkHosts != null && !zkHosts.isEmpty()) {
- LOG.info("Connecting to solr cloud using zkHosts="
- + zkHosts);
- try {
- // Instantiate
- HttpClientUtil.setConfigurer(new Krb5HttpClientConfigurer());
- CloudSolrClient solrCloudClient = new CloudSolrClient(
- zkHosts);
- solrCloudClient.setDefaultCollection(collectionName);
- solrClient = solrCloudClient;
- } catch (Throwable t) {
- LOG.fatal("Can't connect to Solr server. ZooKeepers="
- + zkHosts, t);
+ SolrClient me = solrClient;
+ if (me == null) {
+ synchronized(SolrAuditDestination.class) {
+ me = solrClient;
+ if (solrClient == null) {
+ String urls = MiscUtil.getStringProperty(props, propPrefix
+ + "." + PROP_SOLR_URLS);
+ if (urls != null) {
+ urls = urls.trim();
}
- finally {
- resetInitializerInSOLR() ;
+ if (urls != null && urls.equalsIgnoreCase("NONE")) {
+ urls = null;
}
- } else if (solrURLs != null && !solrURLs.isEmpty()) {
- try {
- LOG.info("Connecting to Solr using URLs=" + solrURLs);
- HttpClientUtil.setConfigurer(new Krb5HttpClientConfigurer());
- LBHttpSolrClient lbSolrClient = new LBHttpSolrClient(
- solrURLs.get(0));
- lbSolrClient.setConnectionTimeout(1000);
+ List solrURLs = new ArrayList();
+ String zkHosts = null;
+ solrURLs = MiscUtil.toArray(urls, ",");
+ zkHosts = MiscUtil.getStringProperty(props, propPrefix + "."
+ + PROP_SOLR_ZK);
+ if (zkHosts != null && zkHosts.equalsIgnoreCase("NONE")) {
+ zkHosts = null;
+ }
+ String collectionName = MiscUtil.getStringProperty(props,
+ propPrefix + "." + PROP_SOLR_COLLECTION);
+ if (collectionName == null
+ || collectionName.equalsIgnoreCase("none")) {
+ collectionName = DEFAULT_COLLECTION_NAME;
+ }
+
+ LOG.info("Solr zkHosts=" + zkHosts + ", solrURLs=" + urls
+ + ", collectionName=" + collectionName);
- for (int i = 1; i < solrURLs.size(); i++) {
- lbSolrClient.addSolrServer(solrURLs.get(i));
+ if (zkHosts != null && !zkHosts.isEmpty()) {
+ LOG.info("Connecting to solr cloud using zkHosts="
+ + zkHosts);
+ try {
+ // Instantiate
+ HttpClientUtil.setConfigurer(new Krb5HttpClientConfigurer());
+ CloudSolrClient solrCloudClient = new CloudSolrClient(
+ zkHosts);
+ solrCloudClient.setDefaultCollection(collectionName);
+ me = solrClient = solrCloudClient;
+ } catch (Throwable t) {
+ LOG.fatal("Can't connect to Solr server. ZooKeepers="
+ + zkHosts, t);
+ }
+ finally {
+ resetInitializerInSOLR() ;
+ }
+ } else if (solrURLs != null && !solrURLs.isEmpty()) {
+ try {
+ LOG.info("Connecting to Solr using URLs=" + solrURLs);
+ HttpClientUtil.setConfigurer(new Krb5HttpClientConfigurer());
+ LBHttpSolrClient lbSolrClient = new LBHttpSolrClient(
+ solrURLs.get(0));
+ lbSolrClient.setConnectionTimeout(1000);
+
+ for (int i = 1; i < solrURLs.size(); i++) {
+ lbSolrClient.addSolrServer(solrURLs.get(i));
+ }
+ me = solrClient = lbSolrClient;
+ } catch (Throwable t) {
+ LOG.fatal("Can't connect to Solr server. URL="
+ + solrURLs, t);
+ }
+ finally {
+ resetInitializerInSOLR() ;
}
- solrClient = lbSolrClient;
- } catch (Throwable t) {
- LOG.fatal("Can't connect to Solr server. URL="
- + solrURLs, t);
- }
- finally {
- resetInitializerInSOLR() ;
}
}
}
}
}
+
private void resetInitializerInSOLR() {
javax.security.auth.login.Configuration solrConfig = javax.security.auth.login.Configuration.getConfiguration();
String solrConfigClassName = solrConfig.getClass().getName() ;
diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/provider/AuditProviderFactory.java b/agents-audit/src/main/java/org/apache/ranger/audit/provider/AuditProviderFactory.java
index e3e818c003..e3c3508241 100644
--- a/agents-audit/src/main/java/org/apache/ranger/audit/provider/AuditProviderFactory.java
+++ b/agents-audit/src/main/java/org/apache/ranger/audit/provider/AuditProviderFactory.java
@@ -67,7 +67,7 @@ public class AuditProviderFactory {
private static final int RANGER_AUDIT_SHUTDOWN_HOOK_PRIORITY = 30;
- private static AuditProviderFactory sFactory;
+ private volatile static AuditProviderFactory sFactory = null;
private AuditHandler mProvider = null;
private String componentAppType = "";
@@ -80,15 +80,17 @@ private AuditProviderFactory() {
}
public static AuditProviderFactory getInstance() {
- if (sFactory == null) {
- synchronized (AuditProviderFactory.class) {
- if (sFactory == null) {
- sFactory = new AuditProviderFactory();
+ AuditProviderFactory ret = sFactory;
+ if(ret == null) {
+ synchronized(AuditProviderFactory.class) {
+ ret = sFactory;
+ if(ret == null) {
+ ret = sFactory = new AuditProviderFactory();
}
}
}
- return sFactory;
+ return ret;
}
public static AuditHandler getAuditProvider() {
diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/provider/MiscUtil.java b/agents-audit/src/main/java/org/apache/ranger/audit/provider/MiscUtil.java
index 535894c854..f5b2795aad 100644
--- a/agents-audit/src/main/java/org/apache/ranger/audit/provider/MiscUtil.java
+++ b/agents-audit/src/main/java/org/apache/ranger/audit/provider/MiscUtil.java
@@ -184,7 +184,9 @@ public static String getApplicationType() {
}
public static String getJvmInstanceId() {
- String ret = Integer.toString(Math.abs(sJvmID.toString().hashCode()));
+ Integer val = Integer.valueOf(sJvmID.toString().hashCode());
+ long longVal = val.longValue();
+ String ret = Long.toString(Math.abs(longVal));
return ret;
}
@@ -565,6 +567,10 @@ static public boolean logErrorMessageByInterval(Log useLogger,
*/
static public boolean logErrorMessageByInterval(Log useLogger,
String message, Throwable e) {
+ if (message == null) {
+ return false;
+ }
+
LogHistory log = logHistoryList.get(message);
if (log == null) {
log = new LogHistory();
@@ -636,7 +642,7 @@ public static void authWithConfig(String appName, Configuration config) {
}
} catch (Throwable t) {
logger.fatal("Error logging as appName=" + appName + ", config="
- + config.toString());
+ + config.toString() + ", error=" + t.getMessage());
}
}
@@ -715,7 +721,7 @@ public static void authWithKerberos(String keytab, String principal,
}
} catch (Throwable t) {
- logger.error("Failed to login as [" + spnegoPrincipals + "]", t);
+ logger.error("Failed to login with given keytab and principal", t);
}
}
diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/provider/hdfs/HdfsLogDestination.java b/agents-audit/src/main/java/org/apache/ranger/audit/provider/hdfs/HdfsLogDestination.java
index 0951c6431b..f15b57a76b 100644
--- a/agents-audit/src/main/java/org/apache/ranger/audit/provider/hdfs/HdfsLogDestination.java
+++ b/agents-audit/src/main/java/org/apache/ranger/audit/provider/hdfs/HdfsLogDestination.java
@@ -471,7 +471,7 @@ private void logException(String msg, IOException excp) {
return;
}
- String excpMsgToExclude = EXCP_MSG_FILESYSTEM_CLOSED;;
+ String excpMsgToExclude = EXCP_MSG_FILESYSTEM_CLOSED;
String excpMsg = excp != null ? excp.getMessage() : null;
boolean excpExcludeLogging = (excpMsg != null && excpMsg.contains(excpMsgToExclude));
diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/provider/solr/SolrAuditProvider.java b/agents-audit/src/main/java/org/apache/ranger/audit/provider/solr/SolrAuditProvider.java
index 9388914b49..8b42be0fc6 100644
--- a/agents-audit/src/main/java/org/apache/ranger/audit/provider/solr/SolrAuditProvider.java
+++ b/agents-audit/src/main/java/org/apache/ranger/audit/provider/solr/SolrAuditProvider.java
@@ -42,7 +42,7 @@ public class SolrAuditProvider extends AuditDestination {
public static final String AUDIT_RETRY_WAIT_PROP = "xasecure.audit.solr.retry.ms";
static final Object lock = new Object();
- SolrClient solrClient = null;
+ volatile SolrClient solrClient = null;
Date lastConnectTime = null;
long lastFailTime = 0;
@@ -61,9 +61,11 @@ public void init(Properties props) {
}
void connect() {
- if (solrClient == null) {
+ SolrClient me = solrClient;
+ if (me == null) {
synchronized (lock) {
- if (solrClient == null) {
+ me = solrClient;
+ if (me == null) {
String solrURL = MiscUtil.getStringProperty(props,
"xasecure.audit.solr.solr_url");
@@ -89,7 +91,7 @@ void connect() {
try {
// TODO: Need to support SolrCloud also
- solrClient = new HttpSolrClient(solrURL);
+ me = solrClient = new HttpSolrClient(solrURL);
if (solrClient instanceof HttpSolrClient) {
HttpSolrClient httpSolrClient = (HttpSolrClient) solrClient;
httpSolrClient.setAllowCompression(true);
diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/queue/AuditFileSpool.java b/agents-audit/src/main/java/org/apache/ranger/audit/queue/AuditFileSpool.java
index 17ddab9e7b..8e3c99209d 100644
--- a/agents-audit/src/main/java/org/apache/ranger/audit/queue/AuditFileSpool.java
+++ b/agents-audit/src/main/java/org/apache/ranger/audit/queue/AuditFileSpool.java
@@ -663,7 +663,7 @@ public boolean accept(File pathname) {
}
});
- if (logFiles.length > maxArchiveFiles) {
+ if (logFiles != null && logFiles.length > maxArchiveFiles) {
int filesToDelete = logFiles.length - maxArchiveFiles;
BufferedReader br = new BufferedReader(new FileReader(
indexDoneFile));
diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/utils/InMemoryJAASConfiguration.java b/agents-audit/src/main/java/org/apache/ranger/audit/utils/InMemoryJAASConfiguration.java
index be9cdd39d3..2e8b7689df 100644
--- a/agents-audit/src/main/java/org/apache/ranger/audit/utils/InMemoryJAASConfiguration.java
+++ b/agents-audit/src/main/java/org/apache/ranger/audit/utils/InMemoryJAASConfiguration.java
@@ -148,14 +148,15 @@ public static void init(String propFile) throws Exception {
properties.load(in);
init(properties);
} catch (IOException e) {
- if (in != null) {
- try {
- in.close();
- } catch (Exception exception) {
- // Ignore
- }
- }
throw new Exception("Failed to load JAAS application properties", e);
+ } finally {
+ if ( in != null) {
+ try {
+ in.close();
+ } catch ( Exception e) {
+ //Ignore
+ }
+ }
}
LOG.debug("<== InMemoryJAASConfiguration.init( {} ) ", propFile);
}
diff --git a/agents-common/pom.xml b/agents-common/pom.xml
index 9b378bf20f..32faf616da 100644
--- a/agents-common/pom.xml
+++ b/agents-common/pom.xml
@@ -27,7 +27,7 @@
org.apache.ranger
ranger
- 0.6.0
+ 0.6.4-SNAPSHOT
..
diff --git a/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java
index 3975b18eb8..5f8acfe7be 100644
--- a/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java
+++ b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java
@@ -117,9 +117,7 @@ public ClientResponse run() {
if(response != null && response.getStatus() == 200) {
ret = response.getEntity(ServicePolicies.class);
- } else if(response != null && response.getStatus() == 304) {
- // no change
- } else {
+ } else if(!(response != null && response.getStatus() == 304)) {
RESTResponse resp = RESTResponse.fromClientResponse(response);
LOG.error("Error getting policies. secureMode=" + isSecureMode + ", user=" + user + ", response=" + resp.toString() + ", serviceName=" + serviceName);
@@ -278,9 +276,7 @@ public ClientResponse run() {
if(response != null && response.getStatus() == 200) {
ret = response.getEntity(ServiceTags.class);
- } else if(response != null && response.getStatus() == 304) {
- // no change
- } else {
+ } else if(!(response != null && response.getStatus() == 304)) {
RESTResponse resp = RESTResponse.fromClientResponse(response);
LOG.error("Error getting taggedResources. secureMode=" + isSecureMode + ", user=" + user
+ ", response=" + resp.toString() + ", serviceName=" + serviceName
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/audit/RangerDefaultAuditHandler.java b/agents-common/src/main/java/org/apache/ranger/plugin/audit/RangerDefaultAuditHandler.java
index 66cee76eb7..60d3b0ca8f 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/audit/RangerDefaultAuditHandler.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/audit/RangerDefaultAuditHandler.java
@@ -67,7 +67,9 @@ public void processResults(Collection results) {
Collection events = getAuthzEvents(results);
- logAuthzAudits(events);
+ if (events != null) {
+ logAuthzAudits(events);
+ }
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultAuditHandler.processResults(" + results + ")");
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesAccessedTogetherCondition.java b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesAccessedTogetherCondition.java
index fc9842edc3..b18e7cd660 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesAccessedTogetherCondition.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesAccessedTogetherCondition.java
@@ -72,7 +72,7 @@ public boolean isMatched(final RangerAccessRequest request) {
if (isInitialized && CollectionUtils.isNotEmpty(matchers)) {
RangerRequestedResources resources = RangerAccessRequestUtil.getRequestedResourcesFromContext(request.getContext());
- ret = resources == null ? false : !resources.isMutuallyExcluded(matchers);
+ ret = resources == null ? false : !resources.isMutuallyExcluded(matchers, request.getContext());
} else {
LOG.error("RangerHiveResourcesAccessedTogetherCondition.isMatched() - condition is not initialized correctly and will NOT be enforced");
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesNotAccessedTogetherCondition.java b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesNotAccessedTogetherCondition.java
index 3b8e0094ef..5036a06d82 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesNotAccessedTogetherCondition.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesNotAccessedTogetherCondition.java
@@ -72,7 +72,7 @@ public boolean isMatched(final RangerAccessRequest request) {
if (isInitialized && CollectionUtils.isNotEmpty(matchers)) {
RangerRequestedResources resources = RangerAccessRequestUtil.getRequestedResourcesFromContext(request.getContext());
- ret = resources == null ? true : resources.isMutuallyExcluded(matchers);
+ ret = resources == null ? true : resources.isMutuallyExcluded(matchers, request.getContext());
} else {
LOG.error("RangerHiveResourcesNotAccessedTogetherCondition.isMatched() - Enforcer is not initialized correctly, Mutual Exclusion will NOT be enforced");
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcher.java
index f65f29ebcb..a1ea326d6b 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcher.java
@@ -20,6 +20,7 @@
package org.apache.ranger.plugin.conditionevaluator;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@@ -126,7 +127,7 @@ int[] extractDuration(String value) {
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerTimeOfDayMatcher.extractDuration(" + value + "): duration[" + result + "]");
+ LOG.debug("<== RangerTimeOfDayMatcher.extractDuration(" + value + "): duration:" + Arrays.toString(result));
}
return result;
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerServiceResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerServiceResourceMatcher.java
index 5c1ae64190..637423e309 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerServiceResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerServiceResourceMatcher.java
@@ -19,24 +19,63 @@
package org.apache.ranger.plugin.contextenricher;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceResource;
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
+import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceEvaluator;
+import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
-public class RangerServiceResourceMatcher {
- private final RangerServiceResource serviceResource;
+import java.util.Map;
+
+public class RangerServiceResourceMatcher implements RangerPolicyResourceEvaluator {
+ private final RangerServiceResource serviceResource;
private final RangerPolicyResourceMatcher policyResourceMatcher;
+ private final Integer leafResourceLevel;
public RangerServiceResourceMatcher(final RangerServiceResource serviceResource, RangerPolicyResourceMatcher policyResourceMatcher) {
- this.serviceResource = serviceResource;
+ this.serviceResource = serviceResource;
this.policyResourceMatcher = policyResourceMatcher;
+ this.leafResourceLevel = ServiceDefUtil.getLeafResourceLevel(getServiceDef(), getPolicyResource());
}
public RangerServiceResource getServiceResource() { return serviceResource; }
+ @Override
+ public long getId() {
+ return serviceResource != null ? serviceResource.getId() :-1;
+ }
+
+ @Override
public RangerPolicyResourceMatcher getPolicyResourceMatcher() { return policyResourceMatcher; }
- public boolean isMatch(RangerAccessResource requestedResource) {
- return this.policyResourceMatcher.isExactHeadMatch(requestedResource);
+ @Override
+ public Map getPolicyResource() {
+ return serviceResource != null ? serviceResource.getResourceElements() : null;
+ }
+
+ @Override
+ public RangerResourceMatcher getResourceMatcher(String resourceName) {
+ return policyResourceMatcher != null ? policyResourceMatcher.getResourceMatcher(resourceName) : null;
+ }
+
+ @Override
+ public Integer getLeafResourceLevel() {
+ return leafResourceLevel;
+ }
+
+ @Override
+ public int compareTo(RangerPolicyResourceEvaluator other) {
+ return Long.compare(getId(), other.getId());
+ }
+
+ public boolean isMatch(RangerAccessResource requestedResource, Map evalContext) {
+ return policyResourceMatcher != null ? policyResourceMatcher.isExactHeadMatch(requestedResource, evalContext) : false;
+ }
+
+ RangerServiceDef getServiceDef() {
+ return policyResourceMatcher != null ? policyResourceMatcher.getServiceDef() : null;
}
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
index c397ca123c..1a6e1b2ad4 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
@@ -27,6 +27,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
+import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceResource;
import org.apache.ranger.plugin.model.RangerTag;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
@@ -34,12 +35,16 @@
import org.apache.ranger.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.apache.ranger.plugin.util.RangerPerfTracer;
+import org.apache.ranger.plugin.util.RangerResourceTrie;
import org.apache.ranger.plugin.util.ServiceTags;
import java.io.*;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
public class RangerTagEnricher extends RangerAbstractContextEnricher {
private static final Log LOG = LogFactory.getLog(RangerTagEnricher.class);
@@ -47,16 +52,15 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
private static final Log PERF_CONTEXTENRICHER_INIT_LOG = RangerPerfTracer.getPerfLogger("contextenricher.init");
public static final String TAG_REFRESHER_POLLINGINTERVAL_OPTION = "tagRefresherPollingInterval";
+ public static final String TAG_RETRIEVER_CLASSNAME_OPTION = "tagRetrieverClassName";
+ public static final String TAG_DISABLE_TRIE_PREFILTER_OPTION = "disableTrieLookupPrefilter";
- public static final String TAG_RETRIEVER_CLASSNAME_OPTION = "tagRetrieverClassName";
-
- private RangerTagRefresher tagRefresher = null;
-
- private RangerTagRetriever tagRetriever = null;
-
- ServiceTags serviceTags = null;
-
- List serviceResourceMatchers;
+ private RangerTagRefresher tagRefresher = null;
+ private RangerTagRetriever tagRetriever = null;
+ private ServiceTags serviceTags = null;
+ private List serviceResourceMatchers = null;
+ private Map serviceResourceTrie = null;
+ private boolean disableTrieLookupPrefilter = false;
@Override
public void init() {
@@ -70,6 +74,8 @@ public void init() {
long pollingIntervalMs = getLongOption(TAG_REFRESHER_POLLINGINTERVAL_OPTION, 60 * 1000);
+ disableTrieLookupPrefilter = getBooleanOption(TAG_DISABLE_TRIE_PREFILTER_OPTION, false);
+
if (StringUtils.isNotBlank(tagRetrieverClassName)) {
try {
@@ -126,7 +132,7 @@ public void enrich(RangerAccessRequest request) {
LOG.debug("==> RangerTagEnricher.enrich(" + request + ")");
}
- List matchedTags = findMatchingTags(request.getResource());
+ List matchedTags = findMatchingTags(request.getResource(), request.getContext());
RangerAccessRequestUtil.setRequestTagsInContext(request.getContext(), matchedTags);
@@ -162,8 +168,19 @@ public void setServiceTags(final ServiceTags serviceTags) {
}
+ Map serviceResourceTrie = null;
+
+ if(!disableTrieLookupPrefilter) {
+ serviceResourceTrie = new HashMap();
+
+ for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) {
+ serviceResourceTrie.put(resourceDef.getName(), new RangerResourceTrie(resourceDef, resourceMatchers));
+ }
+ }
+
this.serviceResourceMatchers = resourceMatchers;
- this.serviceTags = serviceTags;
+ this.serviceResourceTrie = serviceResourceTrie;
+ this.serviceTags = serviceTags;
}
@Override
@@ -185,13 +202,13 @@ public boolean preCleanup() {
return ret;
}
- private List findMatchingTags(final RangerAccessResource resource) {
+ private List findMatchingTags(final RangerAccessResource resource, final Map evalContext) {
if (LOG.isDebugEnabled()) {
- LOG.debug("==> RangerTagEnricher.findMatchingTags(" + resource + ")");
+ LOG.debug("==> RangerTagEnricher.findMatchingTags(" + resource + ", " + evalContext + ")");
}
List ret = null;
- final List serviceResourceMatchers = this.serviceResourceMatchers;
+ final List serviceResourceMatchers = getEvaluators(resource);
if (CollectionUtils.isNotEmpty(serviceResourceMatchers)) {
@@ -199,7 +216,7 @@ private List findMatchingTags(final RangerAccessResource resource) {
for (RangerServiceResourceMatcher resourceMatcher : serviceResourceMatchers) {
- boolean matchResult = resourceMatcher.isMatch(resource);
+ boolean matchResult = resourceMatcher.isMatch(resource, evalContext);
if (matchResult) {
if (ret == null) {
@@ -220,7 +237,71 @@ private List findMatchingTags(final RangerAccessResource resource) {
}
if (LOG.isDebugEnabled()) {
- LOG.debug("<== RangerTagEnricher.findMatchingTags(" + resource + ")");
+ LOG.debug("<== RangerTagEnricher.findMatchingTags(" + resource + ", " + evalContext + ")");
+ }
+
+ return ret;
+ }
+
+ private List getEvaluators(RangerAccessResource resource) {
+ List ret = null;
+
+ if(serviceResourceTrie == null) {
+ ret = serviceResourceMatchers;
+ } else {
+ Set resourceKeys = resource == null ? null : resource.getKeys();
+
+ if (CollectionUtils.isNotEmpty(resourceKeys)) {
+ boolean isRetModifiable = false;
+
+ for (String resourceName : resourceKeys) {
+ RangerResourceTrie trie = serviceResourceTrie.get(resourceName);
+
+ if (trie == null) { // if no trie exists for this resource level, ignore and continue to next level
+ continue;
+ }
+
+ List resourceEvaluators = trie.getEvaluatorsForResource(resource.getValue(resourceName));
+
+ if (CollectionUtils.isEmpty(resourceEvaluators)) { // no policies for this resource, bail out
+ ret = null;
+ } else if (ret == null) { // initialize ret with policies found for this resource
+ ret = resourceEvaluators;
+ } else { // remove policies from ret that are not in resourceEvaluators
+ if (isRetModifiable) {
+ ret.retainAll(resourceEvaluators);
+ } else {
+ final List shorterList;
+ final List longerList;
+
+ if (ret.size() < resourceEvaluators.size()) {
+ shorterList = ret;
+ longerList = resourceEvaluators;
+ } else {
+ shorterList = resourceEvaluators;
+ longerList = ret;
+ }
+
+ ret = new ArrayList<>(shorterList);
+ ret.retainAll(longerList);
+ isRetModifiable = true;
+ }
+ }
+
+ if (CollectionUtils.isEmpty(ret)) { // if no policy exists, bail out and return empty list
+ ret = null;
+ break;
+ }
+ }
+ }
+ }
+
+ if(ret == null) {
+ ret = Collections.emptyList();
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerTagEnricher.getEvaluators(" + resource.getAsString() + "): evaluatorCount=" + ret.size());
}
return ret;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
index d8e19b7793..5e94bc722e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
@@ -50,6 +50,10 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria
POLICY_TYPE_ROWFILTER
};
+ public static final String MASK_TYPE_NULL = "MASK_NULL";
+ public static final String MASK_TYPE_NONE = "MASK_NONE";
+ public static final String MASK_TYPE_CUSTOM = "CUSTOM";
+
// For future use
private static final long serialVersionUID = 1L;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
index f6931b375a..2d27961a29 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
@@ -1260,7 +1260,6 @@ public static class RangerResourceDef implements java.io.Serializable {
private String rbKeyDescription = null;
private String rbKeyValidationMessage = null;
-
public RangerResourceDef() {
this(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
}
@@ -1931,6 +1930,7 @@ public int hashCode() {
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result
+ ((rbKeyLabel == null) ? 0 : rbKeyLabel.hashCode());
+
return result;
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
index a89ec19b3d..62bd100188 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
@@ -776,7 +776,7 @@ boolean isValidItemAccesses(List accesses, List resources, String user, Set userGroups, String accessType);
- List getExactMatchPolicies(RangerAccessResource resource);
+ List getExactMatchPolicies(RangerAccessResource resource, Map evalContext);
- List getExactMatchPolicies(Map resources);
+ List getExactMatchPolicies(Map resources, Map evalContext);
List getAllowedPolicies(String user, Set userGroups, String accessType);
RangerResourceAccessInfo getResourceAccessInfo(RangerAccessRequest request);
+ void reorderPolicyEvaluators();
+
boolean preCleanup();
void setUseForwardedIPAddress(boolean useForwardedIPAddress);
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
index f20923cf9e..346453e98f 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
@@ -20,6 +20,7 @@
package org.apache.ranger.plugin.policyengine;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -34,7 +35,13 @@
import org.apache.ranger.plugin.util.RangerPerfTracer;
import org.apache.ranger.plugin.util.ServicePolicies;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
public class RangerPolicyEngineImpl implements RangerPolicyEngine {
private static final Log LOG = LogFactory.getLog(RangerPolicyEngineImpl.class);
@@ -43,6 +50,8 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
private static final Log PERF_POLICYENGINE_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policyengine.request");
private static final Log PERF_POLICYENGINE_AUDIT_LOG = RangerPerfTracer.getPerfLogger("policyengine.audit");
private static final Log PERF_CONTEXTENRICHER_REQUEST_LOG = RangerPerfTracer.getPerfLogger("contextenricher.request");
+ private static final Log PERF_POLICYENGINE_REBALANCE_LOG = RangerPerfTracer.getPerfLogger("policyengine.rebalance");
+ private static final Log PERF_POLICYENGINE_USAGE_LOG = RangerPerfTracer.getPerfLogger("policyengine.usage");
private static final int MAX_POLICIES_FOR_CACHE_TYPE_EVALUATOR = 100;
@@ -51,6 +60,8 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
private List allContextEnrichers;
+ private final Map policyEvaluatorsMap;
+
private boolean useForwardedIPAddress = false;
private String[] trustedProxyAddresses = null;
@@ -63,6 +74,9 @@ public RangerPolicyEngineImpl(String appId, ServicePolicies servicePolicies, Ran
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerPolicyEngine.init(appId=" + appId + ",hashCode=" + Integer.toHexString(System.identityHashCode(this)) + ")");
+ long freeMemory = Runtime.getRuntime().freeMemory();
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory - freeMemory) + ", Free memory:" + freeMemory);
}
if (options == null) {
@@ -129,8 +143,16 @@ public RangerPolicyEngineImpl(String appId, ServicePolicies servicePolicies, Ran
this.allContextEnrichers = tmpList;
+ policyEvaluatorsMap = createPolicyEvaluatorsMap();
+
RangerPerfTracer.log(perf);
+ if (PERF_POLICYENGINE_INIT_LOG.isDebugEnabled()) {
+ long freeMemory = Runtime.getRuntime().freeMemory();
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory - freeMemory) + ", Free memory:" + freeMemory);
+ }
+
if (LOG.isDebugEnabled()) {
LOG.debug("<== RangerPolicyEngineImpl()");
}
@@ -151,9 +173,29 @@ public long getPolicyVersion() {
return policyRepository.getPolicyVersion();
}
+ public RangerPolicyEvaluator getPolicyEvaluator(Long id) {
+ return policyEvaluatorsMap.get(id);
+ }
+
+ public RangerPolicy getPolicy(Long id) {
+ RangerPolicyEvaluator evaluator = getPolicyEvaluator(id);
+ return evaluator != null ? evaluator.getPolicy() : null;
+ }
+
@Override
public RangerAccessResult createAccessResult(RangerAccessRequest request) {
- return new RangerAccessResult(this.getServiceName(), policyRepository.getServiceDef(), request);
+ RangerAccessResult ret = new RangerAccessResult(this.getServiceName(), policyRepository.getServiceDef(), request);
+ switch (policyRepository.getAuditModeEnum()) {
+ case AUDIT_ALL:
+ ret.setIsAudited(true);
+ break;
+ case AUDIT_NONE:
+ ret.setIsAudited(false);
+ break;
+ default:
+ break;
+ }
+ return ret;
}
@Override
@@ -167,6 +209,8 @@ public void preProcess(RangerAccessRequest request) {
((RangerAccessRequestImpl) request).extractAndSetClientIPAddress(useForwardedIPAddress, trustedProxyAddresses);
}
+ RangerAccessRequestUtil.setCurrentUserInContext(request.getContext(), request.getUser());
+
List enrichers = allContextEnrichers;
if(!CollectionUtils.isEmpty(enrichers)) {
@@ -222,6 +266,8 @@ public RangerAccessResult isAccessAllowed(RangerAccessRequest request, RangerAcc
RangerAccessResult ret = isAccessAllowedNoAudit(request);
+ updatePolicyUsageCounts(request, ret);
+
if (resultProcessor != null) {
RangerPerfTracer perfAuditTracer = null;
@@ -280,12 +326,17 @@ public RangerDataMaskResult evalDataMaskPolicies(RangerAccessRequest request, Ra
RangerDataMaskResult ret = new RangerDataMaskResult(getServiceName(), getServiceDef(), request);
if(request != null) {
- List evaluators = policyRepository.getDataMaskPolicyEvaluators();
+ List evaluators = policyRepository.getDataMaskPolicyEvaluators(request.getResource());
for (RangerPolicyEvaluator evaluator : evaluators) {
evaluator.evaluate(request, ret);
if (ret.getIsAccessDetermined() && ret.getIsAuditedDetermined()) {
- break;
+ if(!StringUtils.equalsIgnoreCase(ret.getMaskType(), RangerPolicy.MASK_TYPE_NONE)) {
+ break;
+ } else {
+ ret.setMaskType(null);
+ ret.setIsAccessDetermined(false);
+ }
}
}
}
@@ -295,6 +346,8 @@ public RangerDataMaskResult evalDataMaskPolicies(RangerAccessRequest request, Ra
ret.setIsAudited(false);
}
+ updatePolicyUsageCounts(request, ret);
+
if (resultProcessor != null) {
resultProcessor.processResult(ret);
}
@@ -315,12 +368,16 @@ public RangerRowFilterResult evalRowFilterPolicies(RangerAccessRequest request,
RangerRowFilterResult ret = new RangerRowFilterResult(getServiceName(), getServiceDef(), request);
if(request != null) {
- List evaluators = policyRepository.getRowFilterPolicyEvaluators();
+ List evaluators = policyRepository.getRowFilterPolicyEvaluators(request.getResource());
for (RangerPolicyEvaluator evaluator : evaluators) {
evaluator.evaluate(request, ret);
if (ret.getIsAccessDetermined() && ret.getIsAuditedDetermined()) {
- break;
+ if(StringUtils.isNotEmpty(ret.getFilterExpr())) {
+ break;
+ } else {
+ ret.setIsAccessDetermined(false);
+ }
}
}
}
@@ -330,6 +387,8 @@ public RangerRowFilterResult evalRowFilterPolicies(RangerAccessRequest request,
ret.setIsAudited(false);
}
+ updatePolicyUsageCounts(request, ret);
+
if (resultProcessor != null) {
resultProcessor.processResult(ret);
}
@@ -354,7 +413,7 @@ public boolean isAccessAllowed(RangerAccessResource resource, String user, Set resources, Stri
}
@Override
- public List getExactMatchPolicies(RangerAccessResource resource) {
+ public List getExactMatchPolicies(RangerAccessResource resource, Map evalContext) {
if (LOG.isDebugEnabled()) {
- LOG.debug("==> RangerPolicyEngineImpl.getExactMatchPolicies(" + resource + ")");
+ LOG.debug("==> RangerPolicyEngineImpl.getExactMatchPolicies(" + resource + ", " + evalContext + ")");
}
List ret = null;
for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
- if (evaluator.isCompleteMatch(resource)) {
+ if (evaluator.isCompleteMatch(resource, evalContext)) {
if(ret == null) {
ret = new ArrayList();
}
@@ -422,22 +481,22 @@ public List getExactMatchPolicies(RangerAccessResource resource) {
}
if (LOG.isDebugEnabled()) {
- LOG.debug("<== RangerPolicyEngineImpl.getExactMatchPolicies(" + resource + "): " + ret);
+ LOG.debug("<== RangerPolicyEngineImpl.getExactMatchPolicies(" + resource + ", " + evalContext + "): " + ret);
}
return ret;
}
@Override
- public List getExactMatchPolicies(Map resources) {
+ public List getExactMatchPolicies(Map resources, Map evalContext) {
if (LOG.isDebugEnabled()) {
- LOG.debug("==> RangerPolicyEngineImpl.getExactMatchPolicies(" + resources + ")");
+ LOG.debug("==> RangerPolicyEngineImpl.getExactMatchPolicies(" + resources + ", " + evalContext + ")");
}
List ret = null;
for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
- if (evaluator.isCompleteMatch(resources)) {
+ if (evaluator.isCompleteMatch(resources, evalContext)) {
if(ret == null) {
ret = new ArrayList();
}
@@ -447,7 +506,7 @@ public List getExactMatchPolicies(Map tagPolicyEvaluators = tagPolicyRepository == null ? null : tagPolicyRepository.getPolicyEvaluators();
- List resPolicyEvaluators = policyRepository.getPolicyEvaluators();
if (CollectionUtils.isNotEmpty(tagPolicyEvaluators)) {
List tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext());
@@ -497,13 +555,17 @@ public RangerResourceAccessInfo getResourceAccessInfo(RangerAccessRequest reques
for (RangerTag tag : tags) {
RangerAccessRequest tagEvalRequest = new RangerTagAccessRequest(tag, tagPolicyRepository.getServiceDef(), request);
- for (RangerPolicyEvaluator evaluator : tagPolicyEvaluators) {
+ List evaluators = tagPolicyRepository.getPolicyEvaluators(tagEvalRequest.getResource());
+
+ for (RangerPolicyEvaluator evaluator : evaluators) {
evaluator.getResourceAccessInfo(tagEvalRequest, ret);
}
}
}
}
+ List resPolicyEvaluators = policyRepository.getPolicyEvaluators(request.getResource());
+
if(CollectionUtils.isNotEmpty(resPolicyEvaluators)) {
for (RangerPolicyEvaluator evaluator : resPolicyEvaluators) {
evaluator.getResourceAccessInfo(request, ret);
@@ -550,8 +612,9 @@ protected RangerAccessResult isAccessAllowedNoAudit(RangerAccessRequest request)
ret.setIsAccessDetermined(false); // discard allowed result by tag-policies, to evaluate resource policies for possible deny
}
- List evaluators = policyRepository.getPolicyEvaluators();
+ List evaluators = policyRepository.getPolicyEvaluators(request.getResource());
for (RangerPolicyEvaluator evaluator : evaluators) {
+ ret.incrementEvaluatedPoliciesCount();
evaluator.evaluate(request, ret);
if(ret.getIsAllowed() && !evaluator.hasDeny()) { // all policies having deny have been evaluated
@@ -585,9 +648,9 @@ protected void isAccessAllowedForTagPolicies(final RangerAccessRequest request,
LOG.debug("==> RangerPolicyEngineImpl.isAccessAllowedForTagPolicies(" + request + ", " + result + ")");
}
- List evaluators = tagPolicyRepository == null ? null : tagPolicyRepository.getPolicyEvaluators();
+ List tagEvaluators = tagPolicyRepository == null ? null : tagPolicyRepository.getPolicyEvaluators();
- if (CollectionUtils.isNotEmpty(evaluators)) {
+ if (CollectionUtils.isNotEmpty(tagEvaluators)) {
List tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext());
if(CollectionUtils.isNotEmpty(tags)) {
@@ -607,9 +670,10 @@ protected void isAccessAllowedForTagPolicies(final RangerAccessRequest request,
}
tagEvalResult.setAuditResultFrom(result);
+ List evaluators = tagPolicyRepository.getPolicyEvaluators(tagEvalRequest.getResource());
+
for (RangerPolicyEvaluator evaluator : evaluators) {
- if(! evaluator.isMatch(tagEvalRequest.getResource()))
- continue;
+ tagEvalResult.incrementEvaluatedPoliciesCount();
evaluator.evaluate(tagEvalRequest, tagEvalResult);
@@ -632,6 +696,7 @@ protected void isAccessAllowedForTagPolicies(final RangerAccessRequest request,
if (tagEvalResult.getIsAudited()) {
result.setIsAudited(true);
+ result.setAuditPolicyId(tagEvalResult.getAuditPolicyId());
}
if(!result.getIsAccessDetermined() && tagEvalResult.getIsAccessDetermined()) {
@@ -658,25 +723,40 @@ protected void isAccessAllowedForTagPolicies(final RangerAccessRequest request,
}
}
- private void setResourceServiceDef(RangerAccessRequest request) {
- RangerAccessResource resource = request.getResource();
+ @Override
+ public void reorderPolicyEvaluators() {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> reorderEvaluators()");
+ }
+ RangerPerfTracer perf = null;
- if (resource.getServiceDef() == null) {
- if (resource instanceof RangerMutableResource) {
- RangerMutableResource mutable = (RangerMutableResource) resource;
- mutable.setServiceDef(getServiceDef());
- } else {
- LOG.debug("RangerPolicyEngineImpl.setResourceServiceDef(): Cannot set ServiceDef in RangerTagResourceMap.");
+ if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_REBALANCE_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REBALANCE_LOG, "RangerPolicyEngine.reorderEvaluators()");
+ }
+ if (MapUtils.isNotEmpty(policyEvaluatorsMap)) {
+ for (Map.Entry entry : policyEvaluatorsMap.entrySet()) {
+ entry.getValue().setUsageCountImmutable();
}
}
- }
- private boolean hasTagPolicies() {
- return tagPolicyRepository != null && CollectionUtils.isNotEmpty(tagPolicyRepository.getPolicies());
- }
+ if (tagPolicyRepository != null) {
+ tagPolicyRepository.reorderPolicyEvaluators();
+ }
+ if (policyRepository != null) {
+ policyRepository.reorderPolicyEvaluators();
+ }
- private boolean hasResourcePolicies() {
- return policyRepository != null && CollectionUtils.isNotEmpty(policyRepository.getPolicies());
+ if (MapUtils.isNotEmpty(policyEvaluatorsMap)) {
+ for (Map.Entry entry : policyEvaluatorsMap.entrySet()) {
+ entry.getValue().resetUsageCount();
+ }
+ }
+
+ RangerPerfTracer.log(perf);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== reorderEvaluators()");
+ }
}
@Override
@@ -774,6 +854,100 @@ public StringBuilder toString(StringBuilder sb) {
return sb;
}
+
+
+ private void setResourceServiceDef(RangerAccessRequest request) {
+ RangerAccessResource resource = request.getResource();
+
+ if (resource.getServiceDef() == null) {
+ if (resource instanceof RangerMutableResource) {
+ RangerMutableResource mutable = (RangerMutableResource) resource;
+ mutable.setServiceDef(getServiceDef());
+ } else {
+ LOG.debug("RangerPolicyEngineImpl.setResourceServiceDef(): Cannot set ServiceDef in RangerTagResourceMap.");
+ }
+ }
+ }
+
+ private boolean hasTagPolicies() {
+ return tagPolicyRepository != null && CollectionUtils.isNotEmpty(tagPolicyRepository.getPolicies());
+ }
+
+ private boolean hasResourcePolicies() {
+ return policyRepository != null && CollectionUtils.isNotEmpty(policyRepository.getPolicies());
+ }
+
+ private Map createPolicyEvaluatorsMap() {
+ Map tmpPolicyEvaluatorMap = new HashMap();
+
+ if (tagPolicyRepository != null) {
+ for (RangerPolicyEvaluator evaluator : tagPolicyRepository.getPolicyEvaluators()) {
+ tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getId(), evaluator);
+ }
+ for (RangerPolicyEvaluator evaluator : tagPolicyRepository.getDataMaskPolicyEvaluators()) {
+ tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getId(), evaluator);
+ }
+ for (RangerPolicyEvaluator evaluator : tagPolicyRepository.getRowFilterPolicyEvaluators()) {
+ tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getId(), evaluator);
+ }
+ }
+ for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
+ tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getId(), evaluator);
+ }
+ for (RangerPolicyEvaluator evaluator : policyRepository.getDataMaskPolicyEvaluators()) {
+ tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getId(), evaluator);
+ }
+ for (RangerPolicyEvaluator evaluator : policyRepository.getRowFilterPolicyEvaluators()) {
+ tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getId(), evaluator);
+ }
+
+ return Collections.unmodifiableMap(tmpPolicyEvaluatorMap);
+ }
+
+ private void updatePolicyUsageCounts(RangerAccessRequest accessRequest, RangerAccessResult accessResult) {
+
+ boolean auditCountUpdated = false;
+
+ if (accessResult.getIsAccessDetermined()) {
+ RangerPolicyEvaluator accessPolicy = getPolicyEvaluator(accessResult.getPolicyId());
+
+ if (accessPolicy != null) {
+
+ if (accessPolicy.getPolicy().getIsAuditEnabled()) {
+ updateUsageCount(accessPolicy, 2);
+ accessResult.setAuditPolicyId(accessResult.getPolicyId());
+
+ auditCountUpdated = true;
+ } else {
+ updateUsageCount(accessPolicy, 1);
+ }
+
+ }
+ }
+
+ if (!auditCountUpdated && accessResult.getIsAuditedDetermined()) {
+ long auditPolicyId = accessResult.getAuditPolicyId();
+ RangerPolicyEvaluator auditPolicy = auditPolicyId == -1 ? null : getPolicyEvaluator(auditPolicyId);
+
+ updateUsageCount(auditPolicy, 1);
+ }
+
+ if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_USAGE_LOG)) {
+ RangerAccessRequestImpl rangerAccessRequest = (RangerAccessRequestImpl) accessRequest;
+ RangerPerfTracer perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_USAGE_LOG,
+ "RangerPolicyEngine.usage(accessingUser=" + rangerAccessRequest.getUser()
+ + ",accessedResource=" + rangerAccessRequest.getResource().getAsString()
+ + ",accessType=" + rangerAccessRequest.getAccessType()
+ + ",evaluatedPoliciesCount=" + accessResult.getEvaluatedPoliciesCount() + ")");
+ RangerPerfTracer.logAlways(perf);
+ }
+ }
+
+ private void updateUsageCount(RangerPolicyEvaluator evaluator, int number) {
+ if (evaluator != null) {
+ evaluator.incrementUsageCount(number);
+ }
+ }
}
class RangerTagResource extends RangerAccessResourceImpl {
private static final String KEY_TAG = "tag";
@@ -799,6 +973,7 @@ public RangerTagAccessRequest(RangerTag resourceTag, RangerServiceDef tagService
RangerAccessRequestUtil.setCurrentTagInContext(request.getContext(), resourceTag);
RangerAccessRequestUtil.setCurrentResourceInContext(request.getContext(), request.getResource());
+ RangerAccessRequestUtil.setCurrentUserInContext(request.getContext(), request.getUser());
super.setContext(requestContext);
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineOptions.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineOptions.java
index 805f5a5060..2b2cf9b375 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineOptions.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineOptions.java
@@ -29,4 +29,5 @@ public class RangerPolicyEngineOptions {
public boolean disableCustomConditions = false;
public boolean disableTagPolicyEvaluation = true;
public boolean evaluateDelegateAdminOnly = false;
+ public boolean disableTrieLookupPrefilter = false;
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
index be98f3b96c..ad9b23dcfe 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
@@ -32,16 +32,47 @@
import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
import org.apache.ranger.plugin.store.AbstractServiceStore;
import org.apache.ranger.plugin.util.RangerPerfTracer;
+import org.apache.ranger.plugin.util.RangerResourceTrie;
import org.apache.ranger.plugin.util.ServiceDefUtil;
import org.apache.ranger.plugin.util.ServicePolicies;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
-public class RangerPolicyRepository {
+class RangerPolicyRepository {
private static final Log LOG = LogFactory.getLog(RangerPolicyRepository.class);
private static final Log PERF_CONTEXTENRICHER_INIT_LOG = RangerPerfTracer.getPerfLogger("contextenricher.init");
+ enum AuditModeEnum {
+ AUDIT_ALL, AUDIT_NONE, AUDIT_DEFAULT
+ }
+
+ static private final class AuditInfo {
+ final boolean isAudited;
+ final long auditPolicyId;
+
+ AuditInfo() {
+ this(false, -1);
+ }
+ AuditInfo(boolean isAudited, long auditPolicyId) {
+ this.isAudited = isAudited;
+ this.auditPolicyId = auditPolicyId;
+ }
+ long getAuditPolicyId() {
+ return this.auditPolicyId;
+ }
+ boolean getIsAudited() {
+ return isAudited;
+ }
+ }
+
private final String serviceName;
private final String appId;
private final RangerServiceDef serviceDef;
@@ -51,10 +82,14 @@ public class RangerPolicyRepository {
private List policyEvaluators;
private List dataMaskPolicyEvaluators;
private List rowFilterPolicyEvaluators;
- private final Map accessAuditCache;
+ private final AuditModeEnum auditModeEnum;
+ private final Map accessAuditCache;
private final String componentServiceName;
private final RangerServiceDef componentServiceDef;
+ private final Map policyResourceTrie;
+ private final Map dataMaskResourceTrie;
+ private final Map rowFilterResourceTrie;
RangerPolicyRepository(String appId, ServicePolicies servicePolicies, RangerPolicyEngineOptions options) {
super();
@@ -71,19 +106,47 @@ public class RangerPolicyRepository {
LOG.debug("RangerPolicyRepository : building resource-policy-repository for service " + serviceName);
}
- String propertyName = "ranger.plugin." + serviceName + ".policyengine.auditcachesize";
+ String auditMode = servicePolicies.getAuditMode();
- if (options.cacheAuditResults) {
- final int RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE = 64*1024;
-
- int auditResultCacheSize = RangerConfiguration.getInstance().getInt(propertyName, RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE);
- accessAuditCache = Collections.synchronizedMap(new CacheMap(auditResultCacheSize));
+ if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_ALL)) {
+ auditModeEnum = AuditModeEnum.AUDIT_ALL;
+ } else if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_NONE)) {
+ auditModeEnum = AuditModeEnum.AUDIT_NONE;
} else {
+ auditModeEnum = AuditModeEnum.AUDIT_DEFAULT;
+ }
+
+ if (auditModeEnum == AuditModeEnum.AUDIT_DEFAULT) {
+ String propertyName = "ranger.plugin." + serviceName + ".policyengine.auditcachesize";
+
+ if (options.cacheAuditResults) {
+ final int RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE = 64 * 1024;
+
+ int auditResultCacheSize = RangerConfiguration.getInstance().getInt(propertyName, RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE);
+ accessAuditCache = Collections.synchronizedMap(new CacheMap(auditResultCacheSize));
+ } else {
accessAuditCache = null;
}
+ } else {
+ this.accessAuditCache = null;
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("RangerPolicyRepository : building policy-repository for service[" + serviceName
+ + "] with auditMode[" + auditModeEnum + "]");
+ }
init(options);
+ if(options.disableTrieLookupPrefilter) {
+ policyResourceTrie = null;
+ dataMaskResourceTrie = null;
+ rowFilterResourceTrie = null;
+ } else {
+ policyResourceTrie = createResourceTrieMap(policyEvaluators);
+ dataMaskResourceTrie = createResourceTrieMap(dataMaskPolicyEvaluators);
+ rowFilterResourceTrie = createResourceTrieMap(rowFilterPolicyEvaluators);
+ }
}
RangerPolicyRepository(String appId, ServicePolicies.TagPolicies tagPolicies, RangerPolicyEngineOptions options,
@@ -100,14 +163,35 @@ public class RangerPolicyRepository {
this.policies = Collections.unmodifiableList(normalizeAndPrunePolicies(tagPolicies.getPolicies(), componentServiceDef.getName()));
this.policyVersion = tagPolicies.getPolicyVersion() != null ? tagPolicies.getPolicyVersion() : -1;
+
+ String auditMode = tagPolicies.getAuditMode();
+
+ if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_ALL)) {
+ auditModeEnum = AuditModeEnum.AUDIT_ALL;
+ } else if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_NONE)) {
+ auditModeEnum = AuditModeEnum.AUDIT_NONE;
+ } else {
+ auditModeEnum = AuditModeEnum.AUDIT_DEFAULT;
+ }
+
this.accessAuditCache = null;
if(LOG.isDebugEnabled()) {
- LOG.debug("RangerPolicyRepository : building tag-policy-repository for tag service " + serviceName);
+ LOG.debug("RangerPolicyRepository : building tag-policy-repository for tag service[" + serviceName
+ + "] with auditMode[" + auditModeEnum +"]");
}
init(options);
+ if(options.disableTrieLookupPrefilter) {
+ policyResourceTrie = null;
+ dataMaskResourceTrie = null;
+ rowFilterResourceTrie = null;
+ } else {
+ policyResourceTrie = createResourceTrieMap(policyEvaluators);
+ dataMaskResourceTrie = createResourceTrieMap(dataMaskPolicyEvaluators);
+ rowFilterResourceTrie = createResourceTrieMap(rowFilterPolicyEvaluators);
+ }
}
public String getServiceName() { return serviceName; }
@@ -126,18 +210,96 @@ public long getPolicyVersion() {
public List getContextEnrichers() { return contextEnrichers; }
- public List getPolicyEvaluators() {
+ List getPolicyEvaluators() {
return policyEvaluators;
}
- public List getDataMaskPolicyEvaluators() {
+ List getPolicyEvaluators(RangerAccessResource resource) {
+ String resourceStr = resource == null ? null : resource.getAsString();
+
+ return policyResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getPolicyEvaluators() : getPolicyEvaluators(policyResourceTrie, resource);
+ }
+
+ List getDataMaskPolicyEvaluators() {
return dataMaskPolicyEvaluators;
}
- public List getRowFilterPolicyEvaluators() {
+ List getDataMaskPolicyEvaluators(RangerAccessResource resource) {
+ String resourceStr = resource == null ? null : resource.getAsString();
+
+ return dataMaskResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getDataMaskPolicyEvaluators() : getPolicyEvaluators(dataMaskResourceTrie, resource);
+ }
+
+ List getRowFilterPolicyEvaluators() {
return rowFilterPolicyEvaluators;
}
+ List getRowFilterPolicyEvaluators(RangerAccessResource resource) {
+ String resourceStr = resource == null ? null : resource.getAsString();
+
+ return rowFilterResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getRowFilterPolicyEvaluators() : getPolicyEvaluators(rowFilterResourceTrie, resource);
+ }
+ AuditModeEnum getAuditModeEnum() { return auditModeEnum; }
+
+ private List getPolicyEvaluators(Map resourceTrie, RangerAccessResource resource) {
+ List ret = null;
+ Set resourceKeys = resource == null ? null : resource.getKeys();
+
+ if(CollectionUtils.isNotEmpty(resourceKeys)) {
+ boolean isRetModifiable = false;
+
+ for(String resourceName : resourceKeys) {
+ RangerResourceTrie trie = resourceTrie.get(resourceName);
+
+ if(trie == null) { // if no trie exists for this resource level, ignore and continue to next level
+ continue;
+ }
+
+ List resourceEvaluators = trie.getEvaluatorsForResource(resource.getValue(resourceName));
+
+ if(CollectionUtils.isEmpty(resourceEvaluators)) { // no policies for this resource, bail out
+ ret = null;
+ } else if(ret == null) { // initialize ret with policies found for this resource
+ ret = resourceEvaluators;
+ } else { // remove policies from ret that are not in resourceEvaluators
+ if(isRetModifiable) {
+ ret.retainAll(resourceEvaluators);
+ } else {
+ final List shorterList;
+ final List longerList;
+
+ if (ret.size() < resourceEvaluators.size()) {
+ shorterList = ret;
+ longerList = resourceEvaluators;
+ } else {
+ shorterList = resourceEvaluators;
+ longerList = ret;
+ }
+
+ ret = new ArrayList<>(shorterList);
+ ret.retainAll(longerList);
+ isRetModifiable = true;
+ }
+ }
+
+ if(CollectionUtils.isEmpty(ret)) { // if no policy exists, bail out and return empty list
+ ret = null;
+ break;
+ }
+ }
+ }
+
+ if(ret == null) {
+ ret = Collections.emptyList();
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerPolicyRepository.getPolicyEvaluators(" + resource.getAsString() + "): evaluatorCount=" + ret.size());
+ }
+
+ return ret;
+ }
+
private RangerServiceDef normalizeAccessTypeDefs(RangerServiceDef serviceDef, final String componentType) {
if (serviceDef != null && StringUtils.isNotBlank(componentType)) {
@@ -283,10 +445,8 @@ private List extends RangerPolicy.RangerPolicyItem> normalizeAndPrunePolicyIte
return policyItems;
}
- public static boolean isDelegateAdminPolicy(RangerPolicy policy) {
- boolean ret = false;
-
- ret = hasDelegateAdminItems(policy.getPolicyItems())
+ private static boolean isDelegateAdminPolicy(RangerPolicy policy) {
+ boolean ret = hasDelegateAdminItems(policy.getPolicyItems())
|| hasDelegateAdminItems(policy.getDenyPolicyItems())
|| hasDelegateAdminItems(policy.getAllowExceptions())
|| hasDelegateAdminItems(policy.getDenyExceptions());
@@ -470,36 +630,27 @@ boolean setAuditEnabledFromCache(RangerAccessRequest request, RangerAccessResult
LOG.debug("==> RangerPolicyRepository.setAuditEnabledFromCache()");
}
- Boolean value = null;
-
- if (accessAuditCache != null) {
- value = accessAuditCache.get(request.getResource().getAsString());
- }
+ final AuditInfo auditInfo = accessAuditCache != null ? accessAuditCache.get(request.getResource().getAsString()) : null;
- if ((value != null)) {
- result.setIsAudited(value);
+ if (auditInfo != null) {
+ result.setIsAudited(auditInfo.getIsAudited());
+ result.setAuditPolicyId(auditInfo.getAuditPolicyId());
}
if (LOG.isDebugEnabled()) {
- LOG.debug("<== RangerPolicyRepository.setAuditEnabledFromCache()");
+ LOG.debug("<== RangerPolicyRepository.setAuditEnabledFromCache():" + (auditInfo != null));
}
- return value != null;
+ return auditInfo != null;
}
- void storeAuditEnabledInCache(RangerAccessRequest request, RangerAccessResult ret) {
+ void storeAuditEnabledInCache(RangerAccessRequest request, RangerAccessResult result) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> RangerPolicyRepository.storeAuditEnabledInCache()");
}
- if ((ret.getIsAuditedDetermined())) {
- String strResource = request.getResource().getAsString();
-
- Boolean value = ret.getIsAudited() ? Boolean.TRUE : Boolean.FALSE;
-
- if (accessAuditCache != null) {
- accessAuditCache.put(strResource, value);
- }
+ if (accessAuditCache != null && result.getIsAuditedDetermined()) {
+ accessAuditCache.put(request.getResource().getAsString(), new AuditInfo(result.getIsAudited(), result.getAuditPolicyId()));
}
if (LOG.isDebugEnabled()) {
@@ -507,11 +658,7 @@ void storeAuditEnabledInCache(RangerAccessRequest request, RangerAccessResult re
}
}
- /**
- * Remove nulls from policy resource values
- * @param policy
- */
- boolean scrubPolicy(RangerPolicy policy) {
+ private boolean scrubPolicy(RangerPolicy policy) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> RangerPolicyRepository.scrubPolicy(" + policy + ")");
}
@@ -538,6 +685,76 @@ boolean scrubPolicy(RangerPolicy policy) {
return altered;
}
+ void reorderPolicyEvaluators() {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> reorderEvaluators()");
+ }
+
+ if(policyResourceTrie != null) {
+ reorderPolicyEvaluators(policyResourceTrie);
+ } else {
+ policyEvaluators = getReorderedPolicyEvaluators(policyEvaluators);
+ }
+
+ if(dataMaskResourceTrie != null) {
+ reorderPolicyEvaluators(dataMaskResourceTrie);
+ } else {
+ dataMaskPolicyEvaluators = getReorderedPolicyEvaluators(dataMaskPolicyEvaluators);
+ }
+
+ if(rowFilterResourceTrie != null) {
+ reorderPolicyEvaluators(rowFilterResourceTrie);
+ } else {
+ rowFilterPolicyEvaluators = getReorderedPolicyEvaluators(rowFilterPolicyEvaluators);
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== reorderEvaluators()");
+ }
+ }
+
+ private void reorderPolicyEvaluators(Map trieMap) {
+ if(trieMap != null) {
+ for(Map.Entry entry : trieMap.entrySet()) {
+ RangerResourceTrie trie = entry.getValue();
+
+ if(trie != null) {
+ trie.reorderEvaluators();
+ }
+ }
+ }
+ }
+
+ private List getReorderedPolicyEvaluators(List evaluators) {
+ List ret = evaluators;
+
+ if (CollectionUtils.isNotEmpty(evaluators)) {
+
+ ret = new ArrayList(evaluators);
+ Collections.sort(ret);
+
+ ret = Collections.unmodifiableList(ret);
+ }
+
+ return ret;
+ }
+
+ private Map createResourceTrieMap(List evaluators) {
+ final Map ret;
+
+ if (CollectionUtils.isNotEmpty(evaluators) && serviceDef != null && CollectionUtils.isNotEmpty(serviceDef.getResources())) {
+ ret = new HashMap();
+
+ for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) {
+ ret.put(resourceDef.getName(), new RangerResourceTrie(resourceDef, evaluators));
+ }
+ } else {
+ ret = null;
+ }
+
+ return ret;
+ }
+
@Override
public String toString( ) {
StringBuilder sb = new StringBuilder();
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
index adc7d8c10b..9b48dfe5ab 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java
@@ -28,13 +28,20 @@
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
+import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceEvaluator;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
+
+import java.util.Map;
public abstract class RangerAbstractPolicyEvaluator implements RangerPolicyEvaluator {
private static final Log LOG = LogFactory.getLog(RangerAbstractPolicyEvaluator.class);
- private RangerPolicy policy = null;
- private RangerServiceDef serviceDef = null;
- private int evalOrder = 0;
+ private RangerPolicy policy = null;
+ private RangerServiceDef serviceDef = null;
+ private Integer leafResourceLevel = null;
+ private int evalOrder = 0;
+ protected long usageCount = 0;
+ protected boolean usageCountMutable = true;
@Override
@@ -43,14 +50,25 @@ public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyE
LOG.debug("==> RangerAbstractPolicyEvaluator.init(" + policy + ", " + serviceDef + ")");
}
- this.policy = policy;
- this.serviceDef = serviceDef;
+ this.policy = policy;
+ this.serviceDef = serviceDef;
+ this.leafResourceLevel = ServiceDefUtil.getLeafResourceLevel(serviceDef, getPolicyResource());
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerAbstractPolicyEvaluator.init(" + policy + ", " + serviceDef + ")");
}
}
+ @Override
+ public long getId() {
+ return policy != null ? policy.getId() :-1;
+ }
+
+ @Override
+ public Map getPolicyResource() {
+ return policy !=null ? policy.getResources() : null;
+ }
+
@Override
public RangerPolicy getPolicy() {
return policy;
@@ -61,6 +79,11 @@ public RangerServiceDef getServiceDef() {
return serviceDef;
}
+ @Override
+ public Integer getLeafResourceLevel() {
+ return leafResourceLevel;
+ }
+
public boolean hasAllow() {
return policy != null && CollectionUtils.isNotEmpty(policy.getPolicyItems());
}
@@ -73,23 +96,44 @@ public boolean hasDeny() {
return policy != null && CollectionUtils.isNotEmpty(policy.getDenyPolicyItems());
}
+ @Override
+ public long getUsageCount() {
+ return usageCount;
+ }
+
@Override
public int getEvalOrder() {
return evalOrder;
}
-
@Override
public boolean isAuditEnabled() {
return policy != null && policy.getIsAuditEnabled();
}
@Override
- public int compareTo(RangerPolicyEvaluator other) {
+ public int compareTo(RangerPolicyResourceEvaluator obj) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerAbstractPolicyEvaluator.compareTo()");
+ LOG.debug("==> RangerAbstractPolicyEvaluator.compareTo()");
}
- int result = Integer.compare(this.getEvalOrder(), other.getEvalOrder());
+ int result;
+
+ if(obj instanceof RangerPolicyEvaluator) {
+ RangerPolicyEvaluator other = (RangerPolicyEvaluator)obj;
+
+ if (hasDeny() && !other.hasDeny()) {
+ result = -1;
+ } else if (!hasDeny() && other.hasDeny()) {
+ result = 1;
+ } else {
+ result = Long.compare(other.getUsageCount(), this.usageCount);
+ if (result == 0) {
+ result = Integer.compare(this.evalOrder, other.getEvalOrder());
+ }
+ }
+ } else {
+ result = Long.compare(getId(), obj.getId());
+ }
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerAbstractPolicyEvaluator.compareTo(), result:" + result);
@@ -102,6 +146,22 @@ public void setEvalOrder(int evalOrder) {
this.evalOrder = evalOrder;
}
+ @Override
+ public void incrementUsageCount(int number) {
+ if (usageCountMutable) usageCount += number;
+ }
+
+ @Override
+ public void setUsageCountImmutable() {
+ this.usageCountMutable = false;
+ }
+
+ @Override
+ public void resetUsageCount() {
+ this.usageCount = 0;
+ this.usageCountMutable = true;
+ }
+
@Override
public String toString( ) {
StringBuilder sb = new StringBuilder();
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java
index 514884fba3..b36bc1f79e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java
@@ -120,7 +120,8 @@ private int computeEvalOrder() {
int evalOrder = RANGER_POLICY_ITEM_EVAL_ORDER_DEFAULT;
if(policyItem != null) {
- if(CollectionUtils.isNotEmpty(policyItem.getGroups()) && policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC)) {
+ if((CollectionUtils.isNotEmpty(policyItem.getGroups()) && policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC))
+ || (CollectionUtils.isNotEmpty(policyItem.getUsers()) && policyItem.getUsers().contains(RangerPolicyEngine.USER_CURRENT))) {
evalOrder -= RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_USERSGROUPS;
} else {
int userGroupCount = 0;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerCachedPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerCachedPolicyEvaluator.java
index 91a53d8b61..7711765faa 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerCachedPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerCachedPolicyEvaluator.java
@@ -26,6 +26,8 @@
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
+import java.util.Map;
+
public class RangerCachedPolicyEvaluator extends RangerOptimizedPolicyEvaluator {
private static final Log LOG = LogFactory.getLog(RangerCachedPolicyEvaluator.class);
@@ -47,34 +49,38 @@ public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyE
}
@Override
- public boolean isMatch(RangerAccessResource resource) {
+ public boolean isMatch(RangerAccessResource resource, Map evalContext) {
if (LOG.isDebugEnabled()) {
- LOG.debug("==> RangerCachedPolicyEvaluator.isMatch(" + resource + ")");
+ LOG.debug("==> RangerCachedPolicyEvaluator.isMatch(" + resource + ", " + evalContext + ")");
}
boolean result = false;
- // Check in the evaluator-owned cache for the match, if found return. else call super.isMatch(), add result to cache
- RangerResourceAccessCache.LookupResult lookup = cache.lookup(resource);
+ if (needsDynamicEval()) {
+ result = super.isMatch(resource, evalContext);
+ } else {
+ // Check in the evaluator-owned cache for the match, if found return. else call super.isMatch(), add result to cache
+ RangerResourceAccessCache.LookupResult lookup = cache.lookup(resource);
- if (lookup != RangerResourceAccessCache.LookupResult.IN_NOTMATCHED_CACHE) {
- // We dont know definitely that this previously not matched
- if (lookup != RangerResourceAccessCache.LookupResult.IN_MATCHED_CACHE) {
- result = super.isMatch(resource);
+ if (lookup != RangerResourceAccessCache.LookupResult.IN_NOTMATCHED_CACHE) {
+ // We dont know definitely that this previously not matched
+ if (lookup != RangerResourceAccessCache.LookupResult.IN_MATCHED_CACHE) {
+ result = super.isMatch(resource, evalContext);
- // update the cache with the result of the match
- if(result) {
- cache.add(resource, RangerResourceAccessCache.CacheType.MATCHED_CACHE);
+ // update the cache with the result of the match
+ if (result) {
+ cache.add(resource, RangerResourceAccessCache.CacheType.MATCHED_CACHE);
+ } else {
+ cache.add(resource, RangerResourceAccessCache.CacheType.NOTMATCHED_CACHE);
+ }
} else {
- cache.add(resource, RangerResourceAccessCache.CacheType.NOTMATCHED_CACHE);
+ result = true;
}
- } else {
- result = true;
}
}
if (LOG.isDebugEnabled()) {
- LOG.debug("<== RangerCachedPolicyEvaluator.isMatch(" + resource + "): " + result);
+ LOG.debug("<== RangerCachedPolicyEvaluator.isMatch(" + resource + ", " + evalContext + "): " + result);
}
return result;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
index 368a695440..867cd208a7 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
@@ -51,6 +51,8 @@
import org.apache.ranger.plugin.policyengine.RangerRowFilterResult;
import org.apache.ranger.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher;
import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
+import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
+import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.apache.ranger.plugin.util.RangerPerfTracer;
import org.apache.ranger.plugin.util.ServiceDefUtil;
@@ -69,13 +71,24 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
private int customConditionsCount = 0;
private List dataMaskEvaluators = null;
private List rowFilterEvaluators = null;
+
private String perfTag;
+ protected boolean needsDynamicEval() { return resourceMatcher != null ? resourceMatcher.getNeedsDynamicEval() : false; }
+
@Override
public int getCustomConditionsCount() {
return customConditionsCount;
}
+ @Override
+ public RangerPolicyResourceMatcher getPolicyResourceMatcher() { return resourceMatcher; }
+
+ @Override
+ public RangerResourceMatcher getResourceMatcher(String resourceName) {
+ return resourceMatcher != null ? resourceMatcher.getResourceMatcher(resourceName) : null;
+ }
+
@Override
public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) {
if(LOG.isDebugEnabled()) {
@@ -161,14 +174,14 @@ public void evaluate(RangerAccessRequest request, RangerAccessResult result) {
if (!result.getIsAuditedDetermined()) {
// Need to match request.resource first. If it matches (or head matches), then only more progress can be made
if (!isResourceMatchAttempted) {
- isResourceMatch = isMatch(request.getResource());
+ isResourceMatch = isMatch(request.getResource(), request.getContext());
isResourceMatchAttempted = true;
}
// Try head match only if match was not found and ANY access was requested
if (!isResourceMatch) {
if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
- isResourceHeadMatch = matchResourceHead(request.getResource());
+ isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
isResourceHeadMatchAttempted = true;
}
}
@@ -177,6 +190,7 @@ public void evaluate(RangerAccessRequest request, RangerAccessResult result) {
// We are done for determining if audit is needed for this policy
if (isAuditEnabled()) {
result.setIsAudited(true);
+ result.setAuditPolicyId(getPolicy().getId());
}
}
}
@@ -186,7 +200,7 @@ public void evaluate(RangerAccessRequest request, RangerAccessResult result) {
if (hasMatchablePolicyItem(request)) {
// Try Match only if it was not attempted as part of evaluating Audit requirement
if (!isResourceMatchAttempted) {
- isResourceMatch = isMatch(request.getResource());
+ isResourceMatch = isMatch(request.getResource(), request.getContext());
isResourceMatchAttempted = true;
}
@@ -194,7 +208,7 @@ public void evaluate(RangerAccessRequest request, RangerAccessResult result) {
// Audit requirement
if (!isResourceMatch) {
if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
- isResourceHeadMatch = matchResourceHead(request.getResource());
+ isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
isResourceHeadMatchAttempted = true;
}
}
@@ -235,13 +249,13 @@ public void evaluate(RangerAccessRequest request, RangerDataMaskResult result) {
if (!result.getIsAuditedDetermined()) {
if (!isResourceMatchAttempted) {
- isResourceMatch = isMatch(request.getResource());
+ isResourceMatch = isMatch(request.getResource(), request.getContext());
isResourceMatchAttempted = true;
}
if (!isResourceMatch) {
if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
- isResourceHeadMatch = matchResourceHead(request.getResource());
+ isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
isResourceHeadMatchAttempted = true;
}
}
@@ -249,19 +263,20 @@ public void evaluate(RangerAccessRequest request, RangerDataMaskResult result) {
if (isResourceMatch || isResourceHeadMatch) {
if (isAuditEnabled()) {
result.setIsAudited(true);
+ result.setAuditPolicyId(getPolicy().getId());
}
}
}
if (!result.getIsAccessDetermined()) {
if (!isResourceMatchAttempted) {
- isResourceMatch = isMatch(request.getResource());
+ isResourceMatch = isMatch(request.getResource(), request.getContext());
isResourceMatchAttempted = true;
}
if (!isResourceMatch) {
if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
- isResourceHeadMatch = matchResourceHead(request.getResource());
+ isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
isResourceHeadMatchAttempted = true;
}
}
@@ -270,6 +285,7 @@ public void evaluate(RangerAccessRequest request, RangerDataMaskResult result) {
evaluatePolicyItems(request, result);
}
}
+
}
RangerPerfTracer.log(perf);
@@ -300,13 +316,13 @@ public void evaluate(RangerAccessRequest request, RangerRowFilterResult result)
if (!result.getIsAuditedDetermined()) {
if (!isResourceMatchAttempted) {
- isResourceMatch = isMatch(request.getResource());
+ isResourceMatch = isMatch(request.getResource(), request.getContext());
isResourceMatchAttempted = true;
}
if (!isResourceMatch) {
if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
- isResourceHeadMatch = matchResourceHead(request.getResource());
+ isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
isResourceHeadMatchAttempted = true;
}
}
@@ -314,19 +330,20 @@ public void evaluate(RangerAccessRequest request, RangerRowFilterResult result)
if (isResourceMatch || isResourceHeadMatch) {
if (isAuditEnabled()) {
result.setIsAudited(true);
+ result.setAuditPolicyId(getPolicy().getId());
}
}
}
if (!result.getIsAccessDetermined()) {
if (!isResourceMatchAttempted) {
- isResourceMatch = isMatch(request.getResource());
+ isResourceMatch = isMatch(request.getResource(), request.getContext());
isResourceMatchAttempted = true;
}
if (!isResourceMatch) {
if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
- isResourceHeadMatch = matchResourceHead(request.getResource());
+ isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
isResourceHeadMatchAttempted = true;
}
}
@@ -345,9 +362,9 @@ public void evaluate(RangerAccessRequest request, RangerRowFilterResult result)
}
@Override
- public boolean isMatch(RangerAccessResource resource) {
+ public boolean isMatch(RangerAccessResource resource, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resource + ")");
+ LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
@@ -355,32 +372,32 @@ public boolean isMatch(RangerAccessResource resource) {
RangerPerfTracer perf = null;
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) {
- perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.isMatch(resource=" + resource.getAsString() + "," + perfTag + ")");
+ perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.isMatch(resource=" + resource.getAsString() + "," + evalContext + "," + perfTag + ")");
}
if(resourceMatcher != null) {
- ret = resourceMatcher.isMatch(resource);
+ ret = resourceMatcher.isMatch(resource, evalContext);
}
RangerPerfTracer.log(perf);
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resource + "): " + ret);
+ LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resource + ", " + evalContext + "): " + ret);
}
return ret;
}
@Override
- public boolean isCompleteMatch(RangerAccessResource resource) {
+ public boolean isCompleteMatch(RangerAccessResource resource, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resource + ")");
+ LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
if(resourceMatcher != null) {
- ret = resourceMatcher.isCompleteMatch(resource);
+ ret = resourceMatcher.isCompleteMatch(resource, evalContext);
}
if(LOG.isDebugEnabled()) {
@@ -391,19 +408,19 @@ public boolean isCompleteMatch(RangerAccessResource resource) {
}
@Override
- public boolean isCompleteMatch(Map resources) {
+ public boolean isCompleteMatch(Map resources, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ")");
+ LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ", " + evalContext + ")");
}
boolean ret = false;
if(resourceMatcher != null) {
- ret = resourceMatcher.isCompleteMatch(resources);
+ ret = resourceMatcher.isCompleteMatch(resources, evalContext);
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + "): " + ret);
+ LOG.debug("<== RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ", " + evalContext + "): " + ret);
}
return ret;
@@ -415,7 +432,10 @@ public boolean isAccessAllowed(RangerAccessResource resource, String user, Set RangerDefaultPolicyEvaluator.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + accessType + ")");
}
- boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resource);
+ Map evalContext = new HashMap();
+ RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
+
+ boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resource, evalContext);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret);
@@ -430,7 +450,10 @@ public boolean isAccessAllowed(Map resources, Stri
LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + ")");
}
- boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resources);
+ Map evalContext = new HashMap();
+ RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
+
+ boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resources, evalContext);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret);
@@ -445,9 +468,9 @@ public void getResourceAccessInfo(RangerAccessRequest request, RangerResourceAcc
LOG.debug("==> RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + result + ")");
}
- final boolean isResourceMatch = isMatch(request.getResource());
+ final boolean isResourceMatch = isMatch(request.getResource(), request.getContext());
final boolean attemptResourceHeadMatch = request.isAccessTypeAny() || request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS;
- final boolean isResourceHeadMatch = (!isResourceMatch && attemptResourceHeadMatch) ? matchResourceHead(request.getResource()) : false;
+ final boolean isResourceHeadMatch = (!isResourceMatch && attemptResourceHeadMatch) ? matchResourceHead(request.getResource(), request.getContext()) : false;
if(isResourceMatch || isResourceHeadMatch) {
if (CollectionUtils.isNotEmpty(allowEvaluators)) {
@@ -630,37 +653,37 @@ private void getResourceAccessInfo(RangerAccessRequest request, List extends R
}
- protected boolean matchResourceHead(RangerAccessResource resource) {
+ protected boolean matchResourceHead(RangerAccessResource resource, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyEvaluator.matchResourceHead(" + resource + ")");
+ LOG.debug("==> RangerDefaultPolicyEvaluator.matchResourceHead(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
if(resourceMatcher != null) {
- ret = resourceMatcher.isHeadMatch(resource);
+ ret = resourceMatcher.isHeadMatch(resource, evalContext);
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyEvaluator.matchResourceHead(" + resource + "): " + ret);
+ LOG.debug("<== RangerDefaultPolicyEvaluator.matchResourceHead(" + resource + ", " + evalContext + "): " + ret);
}
return ret;
}
- protected boolean isMatch(Map resources) {
+ protected boolean isMatch(Map resources, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resources + ")");
+ LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resources + ", " + evalContext + ")");
}
boolean ret = false;
if(resourceMatcher != null) {
- ret = resourceMatcher.isMatch(resources);
+ ret = resourceMatcher.isMatch(resources, evalContext);
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resources + "): " + ret);
+ LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resources + ", " + evalContext + "): " + ret);
}
return ret;
@@ -990,5 +1013,6 @@ private T getMatchingPolicyItem(String use
}
return ret;
- }
+ }
+
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
index e2c715f439..b899dd1c2b 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
@@ -20,6 +20,7 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
@@ -48,6 +49,8 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv
private static final Log PERF_POLICYCONDITION_INIT_LOG = RangerPerfTracer.getPerfLogger("policycondition.init");
private static final Log PERF_POLICYCONDITION_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policycondition.request");
+ private boolean hasCurrentUser = false;
+
public RangerDefaultPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, int policyItemType, int policyItemIndex, RangerPolicyEngineOptions options) {
super(serviceDef, policy, policyItem, policyItemType, policyItemIndex, options);
}
@@ -100,6 +103,9 @@ public void init() {
RangerPerfTracer.log(perf);
}
+ List users = policyItem != null ? policyItem.getUsers() : null;
+ this.hasCurrentUser = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.USER_CURRENT);
+
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", conditionsCount=" + getConditionEvaluators().size() + ")");
}
@@ -172,7 +178,7 @@ public boolean matchUserGroup(String user, Set userGroups) {
if(policyItem != null) {
if(!ret && user != null && policyItem.getUsers() != null) {
- ret = policyItem.getUsers().contains(user);
+ ret = hasCurrentUser || policyItem.getUsers().contains(user);
}
if(!ret && userGroups != null && policyItem.getGroups() != null) {
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
index 2e777aedbf..fb854d0a70 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
@@ -40,14 +40,13 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
private boolean delegateAdmin = false;
private boolean hasAllPerms = false;
private boolean hasPublicGroup = false;
-
+ private boolean hasCurrentUser = false;
// For computation of priority
private static final String RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING = "*";
private static final String RANGER_POLICY_EVAL_MATCH_ONE_CHARACTER_STRING = "?";
private static final int RANGER_POLICY_EVAL_SCORE_DEFAULT = 10000;
- private static final int RANGER_POLICY_EVAL_SCORE_DISCOUNT_POLICY_HAS_DENY = 4000;
private static final int RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_RESOURCE = 100;
private static final int RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_USERSGROUPS = 25;
@@ -60,7 +59,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
private static final int RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_IS_EXCLUDES = 5;
private static final int RANGER_POLICY_EVAL_SCORE_RESORUCE_DISCOUNT_IS_RECURSIVE = 5;
private static final int RANGER_POLICY_EVAL_SCORE_CUSTOM_CONDITION_PENALTY = 5;
-
+ private static final int RANGER_POLICY_EVAL_SCORE_DYNAMIC_RESOURCE_EVAL_PENALTY = 20;
@Override
public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) {
@@ -78,9 +77,17 @@ public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyE
hasAllPerms = checkIfHasAllPerms();
+ for (String user : users) {
+ if (user.equalsIgnoreCase(RangerPolicyEngine.USER_CURRENT)) {
+ hasCurrentUser = true;
+ break;
+ }
+ }
+
for (String group : groups) {
if (group.equalsIgnoreCase(RangerPolicyEngine.GROUP_PUBLIC)) {
hasPublicGroup = true;
+ break;
}
}
@@ -186,10 +193,13 @@ public int computeEvalOrder() {
}
}
}
+ if (needsDynamicEval()) {
+ evalOrder += RANGER_POLICY_EVAL_SCORE_DYNAMIC_RESOURCE_EVAL_PENALTY;
+ }
evalOrder -= Math.min(RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_RESOURCE, resourceDiscount);
- if (hasPublicGroup) {
+ if (hasPublicGroup || hasCurrentUser) {
evalOrder -= RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_USERSGROUPS;
} else {
evalOrder -= Math.min(groups.size() + users.size(), RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_USERSGROUPS);
@@ -202,10 +212,6 @@ public int computeEvalOrder() {
evalOrder -= customConditionsDiscount;
}
- if (hasDeny()) {
- evalOrder -= RANGER_POLICY_EVAL_SCORE_DISCOUNT_POLICY_HAS_DENY;
- }
-
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerOptimizedPolicyEvaluator.computeEvalOrder(), policyName:" + policy.getName() + ", priority:" + evalOrder);
}
@@ -232,7 +238,7 @@ protected boolean isAccessAllowed(String user, Set userGroups, String ac
protected boolean hasMatchablePolicyItem(RangerAccessRequest request) {
boolean ret = false;
- if (hasPublicGroup || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups())) {
+ if (hasPublicGroup || hasCurrentUser || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups())) {
if(request.isAccessTypeDelegatedAdmin()) {
ret = delegateAdmin;
} else if(hasAllPerms) {
@@ -248,7 +254,7 @@ protected boolean hasMatchablePolicyItem(RangerAccessRequest request) {
private boolean hasMatchablePolicyItem(String user, Set userGroups, String accessType) {
boolean ret = false;
- if (hasPublicGroup || users.contains(user) || CollectionUtils.containsAny(groups, userGroups)) {
+ if (hasPublicGroup || hasCurrentUser || users.contains(user) || CollectionUtils.containsAny(groups, userGroups)) {
boolean isAdminAccess = StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS);
if(isAdminAccess) {
@@ -281,6 +287,7 @@ private void preprocessPolicyItems(List extends RangerPolicy.RangerPolicyItem>
groups.addAll(item.getGroups());
users.addAll(item.getUsers());
+
}
}
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
index be97830eff..92f15929b0 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
@@ -33,9 +33,10 @@
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
import org.apache.ranger.plugin.policyengine.RangerResourceAccessInfo;
import org.apache.ranger.plugin.policyengine.RangerRowFilterResult;
+import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceEvaluator;
-public interface RangerPolicyEvaluator extends Comparable {
+public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
String EVALUATOR_TYPE_AUTO = "auto";
String EVALUATOR_TYPE_OPTIMIZED = "optimized";
String EVALUATOR_TYPE_CACHED = "cached";
@@ -52,6 +53,14 @@ public interface RangerPolicyEvaluator extends Comparable
int getEvalOrder();
+ long getUsageCount();
+
+ void incrementUsageCount(int number);
+
+ void setUsageCountImmutable();
+
+ void resetUsageCount();
+
int getCustomConditionsCount();
boolean isAuditEnabled();
@@ -62,15 +71,16 @@ public interface RangerPolicyEvaluator extends Comparable
void evaluate(RangerAccessRequest request, RangerRowFilterResult result);
- boolean isMatch(RangerAccessResource resource);
+ boolean isMatch(RangerAccessResource resource, Map evalContext);
- boolean isCompleteMatch(RangerAccessResource resource);
+ boolean isCompleteMatch(RangerAccessResource resource, Map evalContext);
- boolean isCompleteMatch(Map resources);
+ boolean isCompleteMatch(Map resources, Map evalContext);
boolean isAccessAllowed(RangerAccessResource resource, String user, Set userGroups, String accessType);
boolean isAccessAllowed(Map resources, String user, Set userGroups, String accessType);
void getResourceAccessInfo(RangerAccessRequest request, RangerResourceAccessInfo result);
+
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
index 80e46f55be..20b08c8382 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
@@ -47,7 +47,6 @@ public interface RangerPolicyItemEvaluator extends Comparable userGroups);
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
index 6ea194d69c..5444e2b1e7 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
@@ -48,6 +48,7 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
protected Map policyResources = null;
private Map matchers = null;
+ private boolean needsDynamicEval = false;
private List firstValidResourceDefHierarchy;
@Override
@@ -67,6 +68,11 @@ public void setPolicyResources(Map policyResources
this.policyResources = policyResources;
}
+ @Override
+ public boolean getNeedsDynamicEval() {
+ return needsDynamicEval;
+ }
+
@Override
public void init() {
if(LOG.isDebugEnabled()) {
@@ -133,6 +139,9 @@ public void init() {
RangerResourceMatcher matcher = createResourceMatcher(resourceDef, policyResource);
if (matcher != null) {
+ if (!needsDynamicEval && matcher.getNeedsDynamicEval()) {
+ needsDynamicEval = true;
+ }
matchers.put(resourceName, matcher);
} else {
LOG.error("failed to find matcher for resource " + resourceName);
@@ -162,7 +171,7 @@ public void init() {
String keysString = sb.toString();
String serviceDefName = serviceDef == null ? "" : serviceDef.getName();
String validHierarchy = "";
- if (CollectionUtils.isNotEmpty(firstValidResourceDefHierarchy)) {
+ if (serviceDef != null && CollectionUtils.isNotEmpty(firstValidResourceDefHierarchy)) {
RangerServiceDefHelper serviceDefHelper = new RangerServiceDefHelper(serviceDef, false);
List resourceDefNameOrderedList = serviceDefHelper.getAllResourceNamesOrdered(firstValidResourceDefHierarchy);
@@ -180,9 +189,18 @@ public void init() {
}
@Override
- public boolean isMatch(RangerAccessResource resource) {
+ public RangerServiceDef getServiceDef() {
+ return serviceDef;
+ }
+
+ @Override
+ public RangerResourceMatcher getResourceMatcher(String resourceName) {
+ return matchers != null ? matchers.get(resourceName) : null;
+ }
+
+ public boolean isMatch(RangerAccessResource resource, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + resource + ")");
+ LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
@@ -201,9 +219,9 @@ public boolean isMatch(RangerAccessResource resource) {
// when no value exists for a resourceName, consider it a match only if: policy doesn't have a matcher OR matcher allows no-value resource
if(StringUtils.isEmpty(resourceValue)) {
- ret = matcher == null || matcher.isMatch(resourceValue);
+ ret = matcher == null || matcher.isMatch(resourceValue, evalContext);
} else {
- ret = matcher != null && matcher.isMatch(resourceValue);
+ ret = matcher != null && matcher.isMatch(resourceValue, evalContext);
}
if(! ret) {
@@ -218,7 +236,7 @@ public boolean isMatch(RangerAccessResource resource) {
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + resource + "): " + ret);
+ LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + resource + ", " + evalContext + "): " + ret);
}
return ret;
@@ -226,9 +244,9 @@ public boolean isMatch(RangerAccessResource resource) {
@Override
- public boolean isMatch(Map resources) {
+ public boolean isMatch(Map resources, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + resources + ")");
+ LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + resources + ", " + evalContext + ")");
}
boolean ret = false;
@@ -247,10 +265,10 @@ public boolean isMatch(Map resources) {
// when no value exists for a resourceName, consider it a match only if: policy doesn't have a matcher OR matcher allows no-value resource
if(resourceValues == null || CollectionUtils.isEmpty(resourceValues.getValues())) {
- ret = matcher == null || matcher.isMatch(null);
+ ret = matcher == null || matcher.isMatch(null, null);
} else if(matcher != null) {
for(String resourceValue : resourceValues.getValues()) {
- ret = matcher.isMatch(resourceValue);
+ ret = matcher.isMatch(resourceValue, evalContext);
if(! ret) {
break;
@@ -270,16 +288,16 @@ public boolean isMatch(Map resources) {
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + resources + "): " + ret);
+ LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + resources + ", " + evalContext + "): " + ret);
}
return ret;
}
@Override
- public boolean isCompleteMatch(RangerAccessResource resource) {
+ public boolean isCompleteMatch(RangerAccessResource resource, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + ")");
+ LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
@@ -301,9 +319,9 @@ public boolean isCompleteMatch(RangerAccessResource resource) {
RangerResourceMatcher matcher = matchers == null ? null : matchers.get(resourceName);
if(StringUtils.isEmpty(resourceValue)) {
- ret = matcher == null || matcher.isCompleteMatch(resourceValue);
+ ret = matcher == null || matcher.isCompleteMatch(resourceValue, evalContext);
} else {
- ret = matcher != null && matcher.isCompleteMatch(resourceValue);
+ ret = matcher != null && matcher.isCompleteMatch(resourceValue, evalContext);
}
if(! ret) {
@@ -318,21 +336,21 @@ public boolean isCompleteMatch(RangerAccessResource resource) {
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + "): " + ret);
+ LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + "): " + ret);
}
return ret;
}
@Override
- public boolean isHeadMatch(RangerAccessResource resource) {
+ public boolean isHeadMatch(RangerAccessResource resource, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyResourceMatcher.isHeadMatch(" + resource + ")");
+ LOG.debug("==> RangerDefaultPolicyResourceMatcher.isHeadMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
-
+
if (matchers == null) {
LOG.debug("RangerDefaultPolicyResourceMatcher.isHeadMatch(): PolicyResourceMatcher not initialized correctly!!!");
@@ -345,22 +363,22 @@ public boolean isHeadMatch(RangerAccessResource resource) {
} else {
- ret = newIsHeadMatch(resource);
+ ret = newIsHeadMatch(resource, evalContext);
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyResourceMatcher.matchResourceHead(" + resource + "): " + ret);
+ LOG.debug("<== RangerDefaultPolicyResourceMatcher.matchResourceHead(" + resource + ", " + evalContext + "): " + ret);
}
return ret;
}
@Override
- public boolean isExactHeadMatch(RangerAccessResource resource) {
+ public boolean isExactHeadMatch(RangerAccessResource resource, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyResourceMatcher.isExactHeadMatch(" + resource + ")");
+ LOG.debug("==> RangerDefaultPolicyResourceMatcher.isExactHeadMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
@@ -382,21 +400,21 @@ public boolean isExactHeadMatch(RangerAccessResource resource) {
} else {
- ret = newIsHeadMatch(resource);
+ ret = newIsHeadMatch(resource, evalContext);
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyResourceMatcher.isExactHeadMatch(" + resource + ")" + ret);
+ LOG.debug("<== RangerDefaultPolicyResourceMatcher.isExactHeadMatch(" + resource + ", " + evalContext + ")" + ret);
}
return ret;
}
- private boolean newIsHeadMatch(RangerAccessResource resource) {
+ private boolean newIsHeadMatch(RangerAccessResource resource, Map evalContext) {
if (LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyResourceMatcher.newIsHeadMatch(" + resource + ")");
+ LOG.debug("==> RangerDefaultPolicyResourceMatcher.newIsHeadMatch(" + resource + ", " + evalContext + ")");
}
boolean skipped = false;
@@ -414,7 +432,7 @@ private boolean newIsHeadMatch(RangerAccessResource resource) {
if (!skipped) {
- matched = matcher.isMatch(resourceValue);
+ matched = matcher.isMatch(resourceValue, evalContext);
} else {
@@ -434,7 +452,7 @@ private boolean newIsHeadMatch(RangerAccessResource resource) {
}
if (LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyResourceMatcher.newIsHeadMatch(" + resource + "): " + matched);
+ LOG.debug("<== RangerDefaultPolicyResourceMatcher.newIsHeadMatch(" + resource + ", " + evalContext + "): " + matched);
}
return matched;
@@ -510,9 +528,9 @@ protected static RangerResourceMatcher createResourceMatcher(RangerResourceDef r
}
@Override
- public boolean isCompleteMatch(Map resources) {
+ public boolean isCompleteMatch(Map resources, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ")");
+ LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + evalContext + ")");
}
boolean ret = false;
@@ -551,7 +569,7 @@ public boolean isCompleteMatch(Map resources) {
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + "): " + ret);
+ LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + evalContext + "): " + ret);
}
return ret;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceEvaluator.java
new file mode 100644
index 0000000000..eed58e1ca5
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceEvaluator.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.policyresourcematcher;
+
+
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
+
+import java.util.Map;
+
+public interface RangerPolicyResourceEvaluator extends Comparable {
+ long getId();
+
+ RangerPolicyResourceMatcher getPolicyResourceMatcher();
+
+ Map getPolicyResource();
+
+ RangerResourceMatcher getResourceMatcher(String resourceName);
+
+ Integer getLeafResourceLevel();
+}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
index 54b9586cec..ea0f36c002 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
@@ -25,6 +25,7 @@
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
+import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
public interface RangerPolicyResourceMatcher {
void setServiceDef(RangerServiceDef serviceDef);
@@ -35,17 +36,23 @@ public interface RangerPolicyResourceMatcher {
void init();
- boolean isMatch(RangerAccessResource resource);
+ RangerServiceDef getServiceDef();
- boolean isMatch(Map resources);
+ RangerResourceMatcher getResourceMatcher(String resourceName);
- boolean isCompleteMatch(RangerAccessResource resource);
+ boolean isMatch(RangerAccessResource resource, Map evalContext);
- boolean isHeadMatch(RangerAccessResource resource);
+ boolean isMatch(Map resources, Map evalContext);
- boolean isExactHeadMatch(RangerAccessResource resource);
+ boolean isCompleteMatch(RangerAccessResource resource, Map evalContext);
- boolean isCompleteMatch(Map resources);
+ boolean isHeadMatch(RangerAccessResource resource, Map evalContext);
+
+ boolean isExactHeadMatch(RangerAccessResource resource, Map evalContext);
+
+ boolean isCompleteMatch(Map resources, Map evalContext);
+
+ boolean getNeedsDynamicEval();
StringBuilder toString(StringBuilder sb);
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
index cd725c9f9c..26b9866b5b 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
@@ -20,27 +20,33 @@
package org.apache.ranger.plugin.resourcematcher;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOCase;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
public abstract class RangerAbstractResourceMatcher implements RangerResourceMatcher {
private static final Log LOG = LogFactory.getLog(RangerAbstractResourceMatcher.class);
public final static String WILDCARD_ASTERISK = "*";
- public final static String WILDCARDS = "*?";
- public final static String OPTIONS_SEP = ";";
- public final static String OPTION_NV_SEP = "=";
public final static String OPTION_IGNORE_CASE = "ignoreCase";
public final static String OPTION_WILD_CARD = "wildCard";
+ public final static String OPTION_REPLACE_TOKENS = "replaceTokens";
+ public final static String OPTION_TOKEN_DELIMITER_START = "tokenDelimiterStart";
+ public final static String OPTION_TOKEN_DELIMITER_END = "tokenDelimiterEnd";
+ public final static String OPTION_TOKEN_DELIMITER_ESCAPE = "tokenDelimiterEscape";
+ public final static String OPTION_TOKEN_DELIMITER_PREFIX = "tokenDelimiterPrefix";
protected RangerResourceDef resourceDef = null;
protected RangerPolicyResource policyResource = null;
@@ -48,9 +54,16 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
protected boolean optIgnoreCase = false;
protected boolean optWildCard = false;
- protected List policyValues = null;
- protected boolean policyIsExcludes = false;
- protected boolean isMatchAny = false;
+ protected List policyValues = null;
+ protected boolean policyIsExcludes = false;
+ protected boolean isMatchAny = false;
+ protected ResourceMatcherWrapper resourceMatchers = null;
+
+ protected boolean optReplaceTokens = false;
+ protected char startDelimiterChar = '{';
+ protected char endDelimiterChar = '}';
+ protected char escapeChar = '\\';
+ protected String tokenPrefix = "";
@Override
public void setResourceDef(RangerResourceDef resourceDef) {
@@ -68,44 +81,120 @@ public void init() {
LOG.debug("==> RangerAbstractResourceMatcher.init()");
}
- optIgnoreCase = getBooleanOption(OPTION_IGNORE_CASE, true);
- optWildCard = getBooleanOption(OPTION_WILD_CARD, true);
+ Map options = resourceDef != null ? resourceDef.getMatcherOptions() : null;
+
+ optIgnoreCase = getOptionIgnoreCase(options);
+ optWildCard = getOptionWildCard(options);
- policyValues = new ArrayList();
+ policyValues = new ArrayList();
policyIsExcludes = policyResource == null ? false : policyResource.getIsExcludes();
- if(policyResource != null && policyResource.getValues() != null) {
- boolean isWildCardPresent = false;
- for(String policyValue : policyResource.getValues()) {
- if(StringUtils.isEmpty(policyValue)) {
+ if (policyResource != null && policyResource.getValues() != null) {
+ for (String policyValue : policyResource.getValues()) {
+ if (StringUtils.isEmpty(policyValue)) {
continue;
}
-
- if(optWildCard) {
- if (StringUtils.containsOnly(policyValue, WILDCARD_ASTERISK)) {
- isMatchAny = true;
- } else if (!isWildCardPresent && StringUtils.containsAny(policyValue, WILDCARDS)) {
- isWildCardPresent = true;
- }
- }
policyValues.add(policyValue);
}
- optWildCard = optWildCard && isWildCardPresent;
}
- if(policyValues.isEmpty()) {
- isMatchAny = true;
+ optReplaceTokens = getOptionReplaceTokens(options);
+
+ if(optReplaceTokens) {
+ startDelimiterChar = getOptionDelimiterStart(options);
+ endDelimiterChar = getOptionDelimiterEnd(options);
+ escapeChar = getOptionDelimiterEscape(options);
+ tokenPrefix = getOptionDelimiterPrefix(options);
+
+ if(escapeChar == startDelimiterChar || escapeChar == endDelimiterChar ||
+ tokenPrefix.indexOf(escapeChar) != -1 || tokenPrefix.indexOf(startDelimiterChar) != -1 ||
+ tokenPrefix.indexOf(endDelimiterChar) != -1) {
+ String resouceName = resourceDef == null ? "" : resourceDef.getName();
+
+ String msg = "Invalid token-replacement parameters for resource '" + resouceName + "': { ";
+ msg += (OPTION_TOKEN_DELIMITER_START + "='" + startDelimiterChar + "'; ");
+ msg += (OPTION_TOKEN_DELIMITER_END + "='" + endDelimiterChar + "'; ");
+ msg += (OPTION_TOKEN_DELIMITER_ESCAPE + "='" + escapeChar + "'; ");
+ msg += (OPTION_TOKEN_DELIMITER_PREFIX + "='" + tokenPrefix + "' }. ");
+ msg += "Token replacement disabled";
+
+ LOG.error(msg);
+
+ optReplaceTokens = false;
+ }
}
+ resourceMatchers = buildResourceMatchers();
+ isMatchAny = resourceMatchers == null || CollectionUtils.isEmpty(resourceMatchers.getResourceMatchers());
+
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerAbstractResourceMatcher.init()");
}
}
@Override
- public boolean isCompleteMatch(String resource) {
+ public boolean isMatchAny() { return isMatchAny; }
+
+ public boolean getNeedsDynamicEval() {
+ return resourceMatchers != null && resourceMatchers.getNeedsDynamicEval();
+ }
+
+ public static boolean getOptionIgnoreCase(Map options) {
+ return ServiceDefUtil.getBooleanOption(options, OPTION_IGNORE_CASE, true);
+ }
+
+ public static boolean getOptionWildCard(Map options) {
+ return ServiceDefUtil.getBooleanOption(options, OPTION_WILD_CARD, true);
+ }
+
+ public static boolean getOptionReplaceTokens(Map options) {
+ return ServiceDefUtil.getBooleanOption(options, OPTION_REPLACE_TOKENS, true);
+ }
+
+ public static char getOptionDelimiterStart(Map options) {
+ return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_START, '{');
+ }
+
+ public static char getOptionDelimiterEnd(Map options) {
+ return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_END, '}');
+ }
+
+ public static char getOptionDelimiterEscape(Map options) {
+ return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_ESCAPE, '\\');
+ }
+
+ public static String getOptionDelimiterPrefix(Map options) {
+ return ServiceDefUtil.getOption(options, OPTION_TOKEN_DELIMITER_PREFIX, "");
+ }
+ protected ResourceMatcherWrapper buildResourceMatchers() {
+ List resourceMatchers = new ArrayList();
+ boolean needsDynamicEval = false;
+
+ for (String policyValue : policyValues) {
+ ResourceMatcher matcher = getMatcher(policyValue);
+
+ if (matcher != null) {
+ if (matcher.isMatchAny()) {
+ resourceMatchers.clear();
+ break;
+ }
+ if (!needsDynamicEval && matcher.getNeedsDynamicEval()) {
+ needsDynamicEval = true;
+ }
+ resourceMatchers.add(matcher);
+ }
+ }
+
+ Collections.sort(resourceMatchers);
+
+ return CollectionUtils.isNotEmpty(resourceMatchers) ?
+ new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers) : null;
+ }
+
+ @Override
+ public boolean isCompleteMatch(String resource, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ")");
+ LOG.debug("==> RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
@@ -114,7 +203,7 @@ public boolean isCompleteMatch(String resource) {
ret = StringUtils.isEmpty(resource);
} else if(policyValues.size() == 1) {
String policyValue = policyValues.get(0);
-
+
if(isMatchAny) {
ret = StringUtils.containsOnly(resource, WILDCARD_ASTERISK);
} else {
@@ -127,53 +216,7 @@ public boolean isCompleteMatch(String resource) {
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerAbstractResourceMatcher.isCompleteMatch(" + resource + "): " + ret);
- }
-
- return ret;
- }
-
-
- public String getOption(String name) {
- String ret = null;
-
- Map options = resourceDef != null ? resourceDef.getMatcherOptions() : null;
-
- if(options != null && name != null) {
- ret = options.get(name);
- }
-
- return ret;
- }
-
- public String getOption(String name, String defaultValue) {
- String ret = defaultValue;
- String val = getOption(name);
-
- if(val != null) {
- ret = val;
- }
-
- return ret;
- }
-
- public boolean getBooleanOption(String name, boolean defaultValue) {
- boolean ret = defaultValue;
- String val = getOption(name);
-
- if(val != null) {
- ret = Boolean.parseBoolean(val);
- }
-
- return ret;
- }
-
- public char getCharOption(String name, char defaultValue) {
- char ret = defaultValue;
- String val = getOption(name);
-
- if(! StringUtils.isEmpty(val)) {
- ret = val.charAt(0);
+ LOG.debug("<== RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + "): " + ret);
}
return ret;
@@ -218,7 +261,7 @@ public StringBuilder toString(StringBuilder sb) {
sb.append("options={");
if(resourceDef != null && resourceDef.getMatcherOptions() != null) {
for(Map.Entry e : resourceDef.getMatcherOptions().entrySet()) {
- sb.append(e.getKey()).append("=").append(e.getValue()).append(OPTIONS_SEP);
+ sb.append(e.getKey()).append("=").append(e.getValue()).append(';');
}
}
sb.append("} ");
@@ -228,11 +271,6 @@ public StringBuilder toString(StringBuilder sb) {
return sb;
}
- /**
- * Is resource asking to authorize all possible values at this level?
- * @param resource
- * @return
- */
boolean isAllValuesRequested(String resource) {
boolean result = StringUtils.isEmpty(resource) || WILDCARD_ASTERISK.equals(resource);
if (LOG.isDebugEnabled()) {
@@ -246,13 +284,191 @@ boolean isAllValuesRequested(String resource) {
* - Resource denotes all possible values (i.e. resource in (null, "", "*")
* - where as policy does not allow all possible values (i.e. policy.values().contains("*")
*
- * @param allValuesRequested
- * @param resultWithoutExcludes
- * @return
*/
public boolean applyExcludes(boolean allValuesRequested, boolean resultWithoutExcludes) {
if (!policyIsExcludes) return resultWithoutExcludes; // not an excludes policy!
if (allValuesRequested && !isMatchAny) return resultWithoutExcludes; // one case where excludes has no effect
return !resultWithoutExcludes; // all other cases flip it
}
+
+ ResourceMatcher getMatcher(String policyValue) {
+ final int len = policyValue != null ? policyValue.length() : 0;
+
+ if (len == 0) {
+ return null;
+ }
+
+ final ResourceMatcher ret;
+
+ int wildcardStartIdx = -1;
+ int wildcardEndIdx = -1;
+ boolean needWildcardMatch = false;
+
+ // If optWildcard is true
+ // If ('?' found or non-contiguous '*'s found in policyValue)
+ // needWildcardMatch = true
+ // End
+ //
+ // wildcardStartIdx is set to index of first '*' in policyValue or -1 if '*' is not found in policyValue, and
+ // wildcardEndIdx is set to index of last '*' in policyValue or -1 if '*' is not found in policyValue
+ // Else
+ // needWildcardMatch is set to false
+ // End
+ if (optWildCard) {
+ for (int i = 0; i < len; i++) {
+ final char c = policyValue.charAt(i);
+
+ if (c == '?') {
+ needWildcardMatch = true;
+ break;
+ } else if (c == '*') {
+ if (wildcardEndIdx == -1 || wildcardEndIdx == (i - 1)) {
+ wildcardEndIdx = i;
+ if (wildcardStartIdx == -1) {
+ wildcardStartIdx = i;
+ }
+ } else {
+ needWildcardMatch = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (needWildcardMatch) { // test?, test*a*, test*a*b, *test*a
+ ret = optIgnoreCase ? new CaseInsensitiveWildcardMatcher(policyValue) : new CaseSensitiveWildcardMatcher(policyValue);
+ } else if (wildcardStartIdx == -1) { // test, testa, testab
+ ret = optIgnoreCase ? new CaseInsensitiveStringMatcher(policyValue) : new CaseSensitiveStringMatcher(policyValue);
+ } else if (wildcardStartIdx == 0) { // *test, **test, *testa, *testab
+ String matchStr = policyValue.substring(wildcardEndIdx + 1);
+ ret = optIgnoreCase ? new CaseInsensitiveEndsWithMatcher(matchStr) : new CaseSensitiveEndsWithMatcher(matchStr);
+ } else if (wildcardEndIdx != (len - 1)) { // test*a, test*ab
+ ret = optIgnoreCase ? new CaseInsensitiveWildcardMatcher(policyValue) : new CaseSensitiveWildcardMatcher(policyValue);
+ } else { // test*, test**, testa*, testab*
+ String matchStr = policyValue.substring(0, wildcardStartIdx);
+ ret = optIgnoreCase ? new CaseInsensitiveStartsWithMatcher(matchStr) : new CaseSensitiveStartsWithMatcher(matchStr);
+ }
+
+ if(optReplaceTokens) {
+ ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix);
+ }
+
+ return ret;
+ }
+}
+
+final class CaseSensitiveStringMatcher extends ResourceMatcher {
+ CaseSensitiveStringMatcher(String value) {
+ super(value);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return StringUtils.equals(resourceValue, getExpandedValue(evalContext));
+ }
+ int getPriority() { return 1 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
+}
+
+final class CaseInsensitiveStringMatcher extends ResourceMatcher {
+ CaseInsensitiveStringMatcher(String value) { super(value); }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return StringUtils.equalsIgnoreCase(resourceValue, getExpandedValue(evalContext));
+ }
+ int getPriority() {return 2 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
+final class CaseSensitiveStartsWithMatcher extends ResourceMatcher {
+ CaseSensitiveStartsWithMatcher(String value) {
+ super(value);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return StringUtils.startsWith(resourceValue, getExpandedValue(evalContext));
+ }
+ int getPriority() { return 3 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
}
+
+final class CaseInsensitiveStartsWithMatcher extends ResourceMatcher {
+ CaseInsensitiveStartsWithMatcher(String value) { super(value); }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return StringUtils.startsWithIgnoreCase(resourceValue, getExpandedValue(evalContext));
+ }
+ int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
+final class CaseSensitiveEndsWithMatcher extends ResourceMatcher {
+ CaseSensitiveEndsWithMatcher(String value) {
+ super(value);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return StringUtils.endsWith(resourceValue, getExpandedValue(evalContext));
+ }
+ int getPriority() { return 3 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
+final class CaseInsensitiveEndsWithMatcher extends ResourceMatcher {
+ CaseInsensitiveEndsWithMatcher(String value) {
+ super(value);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return StringUtils.endsWithIgnoreCase(resourceValue, getExpandedValue(evalContext));
+ }
+ int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
+final class CaseSensitiveWildcardMatcher extends ResourceMatcher {
+ CaseSensitiveWildcardMatcher(String value) {
+ super(value);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), IOCase.SENSITIVE);
+ }
+ int getPriority() { return 5 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
+
+final class CaseInsensitiveWildcardMatcher extends ResourceMatcher {
+ CaseInsensitiveWildcardMatcher(String value) {
+ super(value);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), IOCase.INSENSITIVE);
+ }
+ int getPriority() {return 6 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
+final class ResourceMatcherWrapper {
+ private final boolean needsDynamicEval;
+ private final List resourceMatchers;
+
+ ResourceMatcherWrapper() {
+ this(false, null);
+ }
+
+ ResourceMatcherWrapper(boolean needsDynamicEval, List resourceMatchers) {
+ this.needsDynamicEval = needsDynamicEval;
+ this.resourceMatchers = resourceMatchers;
+ }
+
+ boolean getNeedsDynamicEval() {
+ return needsDynamicEval;
+ }
+
+ List getResourceMatchers() {
+ return resourceMatchers;
+ }
+}
+
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcher.java
index 669cf0a112..c1508bf7af 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcher.java
@@ -20,20 +20,19 @@
package org.apache.ranger.plugin.resourcematcher;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOCase;
-import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import java.util.Map;
+
public class RangerDefaultResourceMatcher extends RangerAbstractResourceMatcher {
private static final Log LOG = LogFactory.getLog(RangerDefaultResourceMatcher.class);
@Override
- public boolean isMatch(String resource) {
+ public boolean isMatch(String resource, Map evalContext) {
if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerDefaultResourceMatcher.isMatch(" + resource + ")");
+ LOG.debug("==> RangerDefaultResourceMatcher.isMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
@@ -42,19 +41,13 @@ public boolean isMatch(String resource) {
if(allValuesRequested || isMatchAny) {
ret = isMatchAny;
} else {
- for(String policyValue : policyValues) {
- if(optWildCard) {
- ret = optIgnoreCase ? FilenameUtils.wildcardMatch(resource, policyValue, IOCase.INSENSITIVE)
- : FilenameUtils.wildcardMatch(resource, policyValue, IOCase.SENSITIVE);
- } else {
- ret = optIgnoreCase ? StringUtils.equalsIgnoreCase(resource, policyValue)
- : StringUtils.equals(resource, policyValue);
- }
-
- if(ret) {
+ for (ResourceMatcher resourceMatcher : resourceMatchers.getResourceMatchers()) {
+ ret = resourceMatcher.isMatch(resource, evalContext);
+ if (ret) {
break;
}
}
+
}
ret = applyExcludes(allValuesRequested, ret);
@@ -74,7 +67,7 @@ public boolean isMatch(String resource) {
}
if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerDefaultResourceMatcher.isMatch(" + resource + "): " + ret);
+ LOG.debug("<== RangerDefaultResourceMatcher.isMatch(" + resource + ", " + evalContext + "): " + ret);
}
return ret;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcher.java
index 5c555eb9e4..aeb9fb0e17 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcher.java
@@ -19,27 +19,29 @@
package org.apache.ranger.plugin.resourcematcher;
-
-import java.util.ArrayList;
-import java.util.List;
-
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOCase;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
-public class RangerPathResourceMatcher extends RangerAbstractResourceMatcher {
+public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher {
private static final Log LOG = LogFactory.getLog(RangerPathResourceMatcher.class);
- public static final String OPTION_PATH_SEPERATOR = "pathSeparatorChar";
- public static final char DEFAULT_PATH_SEPERATOR_CHAR = org.apache.hadoop.fs.Path.SEPARATOR_CHAR;
+ private static final String OPTION_PATH_SEPARATOR = "pathSeparatorChar";
+ private static final char DEFAULT_PATH_SEPARATOR_CHAR = org.apache.hadoop.fs.Path.SEPARATOR_CHAR;
- private boolean policyIsRecursive = false;
- private char pathSeparatorChar = DEFAULT_PATH_SEPERATOR_CHAR;
- private List policyValuesForMatch = null;
+ private boolean policyIsRecursive = false;
+ private char pathSeparatorChar = '/';
@Override
public void init() {
@@ -47,76 +49,98 @@ public void init() {
LOG.debug("==> RangerPathResourceMatcher.init()");
}
- super.init();
+ Map options = resourceDef == null ? null : resourceDef.getMatcherOptions();
policyIsRecursive = policyResource == null ? false : policyResource.getIsRecursive();
- pathSeparatorChar = getCharOption(OPTION_PATH_SEPERATOR, DEFAULT_PATH_SEPERATOR_CHAR);
+ pathSeparatorChar = ServiceDefUtil.getCharOption(options, OPTION_PATH_SEPARATOR, DEFAULT_PATH_SEPARATOR_CHAR);
- if(policyIsRecursive && optWildCard && !isMatchAny) {
- policyValuesForMatch = new ArrayList();
+ super.init();
- for(String policyValue : policyValues) {
- if(policyValue.charAt(policyValue.length() - 1) == pathSeparatorChar) {
- policyValuesForMatch.add(policyValue + WILDCARD_ASTERISK);
- } else {
- policyValuesForMatch.add(policyValue);
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerPathResourceMatcher.init()");
+ }
+ }
+
+ @Override
+
+ protected ResourceMatcherWrapper buildResourceMatchers() {
+ List resourceMatchers = new ArrayList();
+ boolean needsDynamicEval = false;
+
+ for (String policyValue : policyValues) {
+ if (optWildCard && policyIsRecursive) {
+ if (policyValue.charAt(policyValue.length() - 1) == pathSeparatorChar) {
+ policyValue += WILDCARD_ASTERISK;
}
}
- } else {
- policyValuesForMatch = policyValues;
- }
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerPathResourceMatcher.init()");
+ ResourceMatcher matcher = getMatcher(policyValue);
+
+ if (matcher != null) {
+ if (matcher.isMatchAny()) {
+ resourceMatchers.clear();
+ break;
+ }
+ if (!needsDynamicEval && matcher.getNeedsDynamicEval()) {
+ needsDynamicEval = true;
+ }
+ resourceMatchers.add(matcher);
+ }
}
+
+ Collections.sort(resourceMatchers);
+
+ return CollectionUtils.isNotEmpty(resourceMatchers) ?
+ new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers) : null;
}
@Override
- public boolean isMatch(String resource) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerPathResourceMatcher.isMatch(" + resource + ")");
+ ResourceMatcher getMatcher(String policyValue) {
+ if(! policyIsRecursive) {
+ return super.getMatcher(policyValue);
}
- boolean ret = false;
- boolean allValuesRequested = isAllValuesRequested(resource);
+ final int len = policyValue != null ? policyValue.length() : 0;
- if(allValuesRequested || isMatchAny) {
- ret = isMatchAny;
- } else {
- IOCase caseSensitivity = optIgnoreCase ? IOCase.INSENSITIVE : IOCase.SENSITIVE;
-
- for(String policyValue : policyValuesForMatch) {
- if(policyIsRecursive && optWildCard) {
- ret = isRecursiveWildCardMatch(resource, policyValue, pathSeparatorChar, caseSensitivity);
- } else if(policyIsRecursive) {
- ret = optIgnoreCase ? StringUtils.startsWithIgnoreCase(resource, policyValue)
- : StringUtils.startsWith(resource, policyValue);
- } else if(optWildCard) {
- ret = FilenameUtils.wildcardMatch(resource, policyValue, caseSensitivity);
- } else {
- ret = optIgnoreCase ? StringUtils.equalsIgnoreCase(resource, policyValue)
- : StringUtils.equals(resource, policyValue);
- }
+ if (len == 0) {
+ return null;
+ }
+
+ // To ensure that when policyValue is single '*', ResourceMatcher created here returns true for isMatchAny()
+ if (optWildCard && policyValue.equals(WILDCARD_ASTERISK)) {
+ return new CaseInsensitiveStringMatcher("");
+ }
+
+ boolean isWildcardPresent = false;
+
+ if (optWildCard) {
+ for (int i = 0; i < len; i++) {
+ final char c = policyValue.charAt(i);
- if(ret) {
+ if (c == '?' || c == '*') {
+ isWildcardPresent = true;
break;
}
}
}
- ret = applyExcludes(allValuesRequested, ret);
+ final ResourceMatcher ret;
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerPathResourceMatcher.isMatch(" + resource + "): " + ret);
+ if (isWildcardPresent) {
+ ret = optIgnoreCase ? new CaseInsensitiveRecursiveWildcardMatcher(policyValue, pathSeparatorChar)
+ : new CaseSensitiveRecursiveWildcardMatcher(policyValue, pathSeparatorChar);
+ } else {
+ ret = optIgnoreCase ? new CaseInsensitiveRecursiveMatcher(policyValue, pathSeparatorChar) : new CaseSensitiveRecursiveMatcher(policyValue, pathSeparatorChar);
+ }
+
+ if (optReplaceTokens) {
+ ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix);
}
return ret;
}
- private boolean isRecursiveWildCardMatch(String pathToCheck, String wildcardPath, char pathSeparatorChar, IOCase caseSensitivity) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerPathResourceMatcher.isRecursiveWildCardMatch(" + pathToCheck + ", " + wildcardPath + ", " + pathSeparatorChar + ")");
- }
+ static boolean isRecursiveWildCardMatch(String pathToCheck, String wildcardPath, char pathSeparatorChar, IOCase caseSensitivity) {
boolean ret = false;
@@ -147,11 +171,6 @@ private boolean isRecursiveWildCardMatch(String pathToCheck, String wildcardPath
ret = FilenameUtils.wildcardMatch(pathToCheck, wildcardPath, caseSensitivity) ;
}
}
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerPathResourceMatcher.isRecursiveWildCardMatch(" + pathToCheck + ", " + wildcardPath + ", " + pathSeparatorChar + "): " + ret);
- }
-
return ret;
}
@@ -167,3 +186,112 @@ public StringBuilder toString(StringBuilder sb) {
return sb;
}
}
+
+final class CaseSensitiveRecursiveWildcardMatcher extends ResourceMatcher {
+ private final char levelSeparatorChar;
+ CaseSensitiveRecursiveWildcardMatcher(String value, char levelSeparatorChar) {
+ super(value);
+ this.levelSeparatorChar = levelSeparatorChar;
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return RangerPathResourceMatcher.isRecursiveWildCardMatch(resourceValue, getExpandedValue(evalContext), levelSeparatorChar, IOCase.SENSITIVE);
+ }
+ int getPriority() { return 7 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
+}
+
+final class CaseInsensitiveRecursiveWildcardMatcher extends ResourceMatcher {
+ private final char levelSeparatorChar;
+ CaseInsensitiveRecursiveWildcardMatcher(String value, char levelSeparatorChar) {
+ super(value);
+ this.levelSeparatorChar = levelSeparatorChar;
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+ return RangerPathResourceMatcher.isRecursiveWildCardMatch(resourceValue, getExpandedValue(evalContext), levelSeparatorChar, IOCase.INSENSITIVE);
+ }
+ int getPriority() { return 8 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
+
+}
+
+abstract class RecursiveMatcher extends ResourceMatcher {
+ final char levelSeparatorChar;
+ String valueWithoutSeparator = null;
+ String valueWithSeparator = null;
+
+ RecursiveMatcher(String value, char levelSeparatorChar) {
+ super(value);
+ this.levelSeparatorChar = levelSeparatorChar;
+ }
+
+ String getStringToCompare(String policyValue) {
+ return (policyValue.lastIndexOf(levelSeparatorChar) == policyValue.length()-1) ?
+ policyValue.substring(0, policyValue.length()-1) : policyValue;
+ }
+}
+
+final class CaseSensitiveRecursiveMatcher extends RecursiveMatcher {
+ CaseSensitiveRecursiveMatcher(String value, char levelSeparatorChar) {
+ super(value, levelSeparatorChar);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+
+ final String noSeparator;
+ if (getNeedsDynamicEval()) {
+ noSeparator = getStringToCompare(getExpandedValue(evalContext));
+ } else {
+ if (valueWithoutSeparator == null) {
+ valueWithoutSeparator = getStringToCompare(value);
+ valueWithSeparator = valueWithoutSeparator + Character.toString(levelSeparatorChar);
+ }
+ noSeparator = valueWithoutSeparator;
+ }
+
+ boolean ret = StringUtils.equals(resourceValue, noSeparator);
+
+ if (!ret) {
+ final String withSeparator = getNeedsDynamicEval() ? noSeparator + Character.toString(levelSeparatorChar) : valueWithSeparator;
+ ret = StringUtils.startsWith(resourceValue, withSeparator);
+ }
+
+ return ret;
+ }
+ int getPriority() { return 7 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
+}
+
+final class CaseInsensitiveRecursiveMatcher extends RecursiveMatcher {
+ CaseInsensitiveRecursiveMatcher(String value, char levelSeparatorChar) {
+ super(value, levelSeparatorChar);
+ }
+
+ @Override
+ boolean isMatch(String resourceValue, Map evalContext) {
+
+ final String noSeparator;
+ if (getNeedsDynamicEval()) {
+ noSeparator = getStringToCompare(getExpandedValue(evalContext));
+ } else {
+ if (valueWithoutSeparator == null) {
+ valueWithoutSeparator = getStringToCompare(value);
+ valueWithSeparator = valueWithoutSeparator + Character.toString(levelSeparatorChar);
+ }
+ noSeparator = valueWithoutSeparator;
+ }
+
+ boolean ret = StringUtils.equalsIgnoreCase(resourceValue, noSeparator);
+
+ if (!ret) {
+ final String withSeparator = getNeedsDynamicEval() ? noSeparator + Character.toString(levelSeparatorChar) : valueWithSeparator;
+ ret = StringUtils.startsWithIgnoreCase(resourceValue, withSeparator);
+ }
+
+ return ret;
+ }
+
+ int getPriority() { return 8 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
+
+}
\ No newline at end of file
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerResourceMatcher.java
index e4d3ce5c83..c1d8366230 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerResourceMatcher.java
@@ -22,6 +22,8 @@
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import java.util.Map;
+
public interface RangerResourceMatcher {
void setResourceDef(RangerResourceDef resourceDef);
@@ -29,7 +31,12 @@ public interface RangerResourceMatcher {
void init();
- boolean isMatch(String resource);
+ boolean isMatchAny();
+
+ boolean isMatch(String resource, Map evalContext);
+
+ boolean isCompleteMatch(String resource, Map evalContext);
+
+ boolean getNeedsDynamicEval();
- boolean isCompleteMatch(String resource);
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
new file mode 100644
index 0000000000..853c525978
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.resourcematcher;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.util.StringTokenReplacer;
+
+import java.util.Map;
+
+abstract class ResourceMatcher implements Comparable {
+ private static final Log LOG = LogFactory.getLog(ResourceMatcher.class);
+
+ protected final String value;
+ protected StringTokenReplacer tokenReplacer;
+
+ static final int DYNAMIC_EVALUATION_PENALTY = 8;
+
+ ResourceMatcher(String value) { this.value = value; }
+
+ abstract boolean isMatch(String resourceValue, Map evalContext);
+ abstract int getPriority();
+
+ boolean isMatchAny() { return value != null && value.length() == 0; }
+
+ boolean getNeedsDynamicEval() {
+ return tokenReplacer != null;
+ }
+
+ @Override
+ public int compareTo(ResourceMatcher other) { return Integer.compare(getPriority(), other.getPriority()); }
+
+ @Override
+ public String toString() {
+ return this.getClass().getName() + "(" + this.value + ")";
+ }
+
+ void setDelimiters(char startDelimiterChar, char endDelimiterChar, char escapeChar, String tokenPrefix) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> setDelimiters(value= " + value + ", startDelimiter=" + startDelimiterChar +
+ ", endDelimiter=" + endDelimiterChar + ", escapeChar=" + escapeChar + ", prefix=" + tokenPrefix);
+ }
+
+ if(value != null && (value.indexOf(escapeChar) != -1 || (value.indexOf(startDelimiterChar) != -1 && value.indexOf(endDelimiterChar) != -1))) {
+ tokenReplacer = new StringTokenReplacer(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix);
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== setDelimiters(value= " + value + ", startDelimiter=" + startDelimiterChar +
+ ", endDelimiter=" + endDelimiterChar + ", escapeChar=" + escapeChar + ", prefix=" + tokenPrefix);
+ }
+ }
+
+ String getExpandedValue(Map evalContext) {
+ final String ret;
+
+ if(tokenReplacer != null) {
+ ret = tokenReplacer.replaceTokens(value, evalContext);
+ } else {
+ ret = value;
+ }
+
+ return ret;
+ }
+}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
index a000125e08..172cb2f163 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
@@ -22,6 +22,8 @@
import java.util.Collection;
import java.util.Hashtable;
import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
@@ -30,7 +32,17 @@
import org.apache.ranger.admin.client.RangerAdminRESTClient;
import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.policyengine.*;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.policyengine.RangerAccessResultProcessor;
+import org.apache.ranger.plugin.policyengine.RangerDataMaskResult;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngineImpl;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
+import org.apache.ranger.plugin.policyengine.RangerResourceAccessInfo;
+import org.apache.ranger.plugin.policyengine.RangerRowFilterResult;
import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
import org.apache.ranger.plugin.util.GrantRevokeRequest;
import org.apache.ranger.plugin.util.PolicyRefresher;
@@ -51,6 +63,7 @@ public class RangerBasePlugin {
private RangerAccessResultProcessor resultProcessor = null;
private boolean useForwardedIPAddress = false;
private String[] trustedProxyAddresses = null;
+ private Timer policyEngineRefreshTimer;
Map logHistoryList = new Hashtable();
int logInterval = 30000; // 30 seconds
@@ -120,12 +133,39 @@ public void init() {
policyEngineOptions.disableContextEnrichers = RangerConfiguration.getInstance().getBoolean(propertyPrefix + ".policyengine.option.disable.context.enrichers", false);
policyEngineOptions.disableCustomConditions = RangerConfiguration.getInstance().getBoolean(propertyPrefix + ".policyengine.option.disable.custom.conditions", false);
policyEngineOptions.disableTagPolicyEvaluation = RangerConfiguration.getInstance().getBoolean(propertyPrefix + ".policyengine.option.disable.tagpolicy.evaluation", false);
+ policyEngineOptions.disableTrieLookupPrefilter = RangerConfiguration.getInstance().getBoolean(propertyPrefix + ".policyengine.option.disable.trie.lookup.prefilter", false);
RangerAdminClient admin = createAdminClient(serviceName, appId, propertyPrefix);
refresher = new PolicyRefresher(this, serviceType, appId, serviceName, admin, pollingIntervalMs, cacheDir);
refresher.setDaemon(true);
refresher.startRefresher();
+
+ long policyReorderIntervalMs = RangerConfiguration.getInstance().getLong(propertyPrefix + ".policy.policyReorderInterval", 60 * 1000);
+ if (policyReorderIntervalMs >= 0 && policyReorderIntervalMs < 15 * 1000) {
+ policyReorderIntervalMs = 15 * 1000;
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(propertyPrefix + ".policy.policyReorderInterval:" + policyReorderIntervalMs);
+ }
+
+ if (policyReorderIntervalMs > 0) {
+ policyEngineRefreshTimer = new Timer("PolicyEngineRefreshTimer", true);
+ try {
+ policyEngineRefreshTimer.schedule(new PolicyEngineRefresher(this), policyReorderIntervalMs, policyReorderIntervalMs);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Scheduled PolicyEngineRefresher to reorder policies nbased on number of evaluations in and every " + policyReorderIntervalMs + " milliseconds");
+ }
+ } catch (IllegalStateException exception) {
+ LOG.error("Error scheduling policyEngineRefresher:", exception);
+ LOG.error("*** PolicyEngine will NOT be reorderd based on number of evaluations every " + policyReorderIntervalMs + " milliseconds ***");
+ policyEngineRefreshTimer = null;
+ }
+ } else {
+ LOG.info("Policies will NOT be reordered based on number of evaluations because "
+ + propertyPrefix + ".policy.policyReorderInterval is set to a negative number[" + policyReorderIntervalMs +"]");
+ }
}
public void setPolicies(ServicePolicies policies) {
@@ -154,17 +194,25 @@ public void cleanup() {
RangerPolicyEngine policyEngine = this.policyEngine;
+ Timer policyEngineRefreshTimer = this.policyEngineRefreshTimer;
+
this.serviceName = null;
this.policyEngine = null;
this.refresher = null;
+ this.policyEngineRefreshTimer = null;
if (refresher != null) {
refresher.stopRefresher();
}
+ if (policyEngineRefreshTimer != null) {
+ policyEngineRefreshTimer.cancel();
+ }
+
if (policyEngine != null) {
policyEngine.cleanup();
}
+
}
public void setResultProcessor(RangerAccessResultProcessor resultProcessor) {
@@ -243,16 +291,6 @@ public RangerResourceAccessInfo getResourceAccessInfo(RangerAccessRequest reques
return null;
}
- public RangerAccessResult createAccessResult(RangerAccessRequest request) {
- RangerPolicyEngine policyEngine = this.policyEngine;
-
- if(policyEngine != null) {
- return policyEngine.createAccessResult(request);
- }
-
- return null;
- }
-
public void grantAccess(GrantRevokeRequest request, RangerAccessResultProcessor resultProcessor) throws Exception {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerAdminRESTClient.grantAccess(" + request + ")");
@@ -400,4 +438,19 @@ static class LogHistory {
int counter=0;
}
+ static private final class PolicyEngineRefresher extends TimerTask {
+ private final RangerBasePlugin plugin;
+
+ PolicyEngineRefresher(RangerBasePlugin plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public void run() {
+ RangerPolicyEngine policyEngine = plugin.policyEngine;
+ if (policyEngine != null) {
+ policyEngine.reorderPolicyEvaluators();
+ }
+ }
+ }
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/file/TagFileStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/file/TagFileStore.java
index a20a9f8da9..780d3796e1 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/file/TagFileStore.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/file/TagFileStore.java
@@ -195,7 +195,7 @@ public void deleteTagDefByName(String name) throws Exception {
RangerTagDef existing = getTagDefByName(name);
- if (existing == null) {
+ if (existing != null) {
try {
deleteTagDef(existing);
} catch (Exception excp) {
@@ -422,7 +422,9 @@ public void deleteTag(Long id) throws Exception {
try {
RangerTag tag = getTag(id);
- deleteTag(tag);
+ if (tag != null) {
+ deleteTag(tag);
+ }
} catch (Exception excp) {
throw new Exception("failed to delete tag with ID=" + id, excp);
}
@@ -667,7 +669,9 @@ public void deleteServiceResource(Long id) throws Exception {
try {
RangerServiceResource resource = getServiceResource(id);
- deleteServiceResource(resource);
+ if (resource != null) {
+ deleteServiceResource(resource);
+ }
} catch (Exception excp) {
throw new Exception("failed to delete service-resource with ID=" + id, excp);
}
@@ -686,7 +690,9 @@ public void deleteServiceResourceByGuid(String guid) throws Exception {
try {
RangerServiceResource resource = getServiceResourceByGuid(guid);
- deleteServiceResource(resource);
+ if (resource != null) {
+ deleteServiceResource(resource);
+ }
} catch (Exception excp) {
throw new Exception("failed to delete service-resource with GUID=" + guid, excp);
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/rest/ServiceRESTStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/rest/ServiceRESTStore.java
index 1cb2175022..4a00d63582 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/rest/ServiceRESTStore.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/rest/ServiceRESTStore.java
@@ -599,9 +599,7 @@ public ClientResponse run() {
if(response != null && response.getStatus() == 200) {
ret = response.getEntity(ServicePolicies.class);
- } else if(response != null && response.getStatus() == 304) {
- // no change
- } else {
+ } else if(!(response != null && response.getStatus() == 304)) {
RESTResponse resp = RESTResponse.fromClientResponse(response);
throw new Exception(resp.getMessage());
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/PerfDataRecorder.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/PerfDataRecorder.java
index ddc42c0a69..3fe96ac70e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/PerfDataRecorder.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/PerfDataRecorder.java
@@ -36,7 +36,6 @@ public class PerfDataRecorder {
private static volatile PerfDataRecorder instance = null;
private Map perfStatistics = new HashMap();
- private boolean initPerfStatisticsOnce = true;
public static void initialize(List names) {
if (instance == null) {
@@ -57,6 +56,13 @@ public static void printStatistics() {
instance.dumpStatistics();
}
}
+
+ public static void clearStatistics() {
+ if (instance != null) {
+ instance.clear();
+ }
+ }
+
public static void recordStatistic(String tag, long elapsedTime) {
if (instance != null) {
instance.record(tag, elapsedTime);
@@ -73,19 +79,16 @@ private void dumpStatistics() {
PerfStatistic perfStatistic = perfStatistics.get(tag);
long averageTimeSpent = 0L;
- long minTimeSpent = 0L;
- long maxTimeSpent = 0L;
+
if (perfStatistic.numberOfInvocations.get() != 0L) {
averageTimeSpent = perfStatistic.millisecondsSpent.get()/perfStatistic.numberOfInvocations.get();
- minTimeSpent = perfStatistic.minTimeSpent.get();
- maxTimeSpent = perfStatistic.maxTimeSpent.get();
}
String logMsg = "[" + tag + "]" +
- " execCount:" + perfStatistic.numberOfInvocations +
- ", totalTimeTaken:" + perfStatistic.millisecondsSpent +
- ", maxTimeTaken:" + maxTimeSpent +
- ", minTimeTaken:" + minTimeSpent +
+ " execCount:" + perfStatistic.numberOfInvocations.get() +
+ ", totalTimeTaken:" + perfStatistic.millisecondsSpent.get() +
+ ", maxTimeTaken:" + perfStatistic.maxTimeSpent.get() +
+ ", minTimeTaken:" + perfStatistic.minTimeSpent.get() +
", avgTimeTaken:" + averageTimeSpent;
LOG.info(logMsg);
@@ -93,23 +96,25 @@ private void dumpStatistics() {
}
}
+ private void clear() {
+ perfStatistics.clear();
+ }
+
private void record(String tag, long elapsedTime) {
PerfStatistic perfStatistic = perfStatistics.get(tag);
- if (perfStatistic == null && !initPerfStatisticsOnce) {
+ if (perfStatistic == null) {
synchronized (PerfDataRecorder.class) {
perfStatistic = perfStatistics.get(tag);
- if (perfStatistic == null) {
+
+ if(perfStatistic == null) {
perfStatistic = new PerfStatistic();
perfStatistics.put(tag, perfStatistic);
}
}
}
- if (perfStatistic != null) {
- perfStatistic.addPerfDataItem(elapsedTime);
- }
-
+ perfStatistic.addPerfDataItem(elapsedTime);
}
private PerfDataRecorder(List names) {
@@ -118,8 +123,6 @@ private PerfDataRecorder(List names) {
// Create structure
perfStatistics.put(name, new PerfStatistic());
}
- } else {
- initPerfStatisticsOnce = false;
}
}
@@ -134,12 +137,12 @@ void addPerfDataItem(final long timeTaken) {
millisecondsSpent.getAndAdd(timeTaken);
long min = minTimeSpent.get();
- if (timeTaken < min) {
+ if(timeTaken < min) {
minTimeSpent.compareAndSet(min, timeTaken);
}
long max = maxTimeSpent.get();
- if (timeTaken > max) {
+ if(timeTaken > max) {
maxTimeSpent.compareAndSet(max, timeTaken);
}
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java
index f865a2a42c..38e05d91c0 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java
@@ -179,6 +179,9 @@ private void loadPolicy() {
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "PolicyRefresher.loadPolicy(serviceName=" + serviceName + ")");
+ long freeMemory = Runtime.getRuntime().freeMemory();
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory-freeMemory) + ", Free memory:" + freeMemory);
}
//load policy from PolicyAdmin
@@ -195,6 +198,12 @@ private void loadPolicy() {
RangerPerfTracer.log(perf);
+ if (PERF_POLICYENGINE_INIT_LOG.isDebugEnabled()) {
+ long freeMemory = Runtime.getRuntime().freeMemory();
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory-freeMemory) + ", Free memory:" + freeMemory);
+ }
+
if (svcPolicies != null) {
plugIn.setPolicies(svcPolicies);
policiesSetInPlugin = true;
@@ -213,6 +222,12 @@ private ServicePolicies loadPolicyfromPolicyAdmin() {
ServicePolicies svcPolicies = null;
+ RangerPerfTracer perf = null;
+
+ if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "PolicyRefresher.loadPolicyFromPolicyAdmin(serviceName=" + serviceName + ")");
+ }
+
try {
svcPolicies = rangerAdmin.getServicePoliciesIfUpdated(lastKnownVersion);
@@ -240,7 +255,9 @@ private ServicePolicies loadPolicyfromPolicyAdmin() {
LOG.error("PolicyRefresher(serviceName=" + serviceName + "): failed to refresh policies. Will continue to use last known version of policies (" + lastKnownVersion + ")", excp);
}
- if(LOG.isDebugEnabled()) {
+ RangerPerfTracer.log(perf);
+
+ if(LOG.isDebugEnabled()) {
LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").loadPolicyfromPolicyAdmin()");
}
@@ -261,6 +278,12 @@ private ServicePolicies loadFromCache() {
if(cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) {
Reader reader = null;
+ RangerPerfTracer perf = null;
+
+ if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "PolicyRefresher.loadFromCache(serviceName=" + serviceName + ")");
+ }
+
try {
reader = new FileReader(cacheFile);
@@ -278,6 +301,8 @@ private ServicePolicies loadFromCache() {
} catch (Exception excp) {
LOG.error("failed to load policies from cache file " + cacheFile.getAbsolutePath(), excp);
} finally {
+ RangerPerfTracer.log(perf);
+
if(reader != null) {
try {
reader.close();
@@ -320,6 +345,13 @@ private void saveToCache(ServicePolicies policies) {
}
if(cacheFile != null) {
+
+ RangerPerfTracer perf = null;
+
+ if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
+ perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "PolicyRefresher.saveToCache(serviceName=" + serviceName + ")");
+ }
+
Writer writer = null;
try {
@@ -337,6 +369,9 @@ private void saveToCache(ServicePolicies policies) {
}
}
}
+
+ RangerPerfTracer.log(perf);
+
}
} else {
LOG.info("policies is null. Nothing to save in cache");
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
index 0ce3721f5c..2f3a39e63e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
@@ -37,6 +37,8 @@ public class RangerAccessRequestUtil {
public static final String KEY_CONTEXT_TAG_OBJECT = "TAG_OBJECT";
public static final String KEY_CONTEXT_RESOURCE = "RESOURCE";
public static final String KEY_CONTEXT_REQUESTED_RESOURCES = "REQUESTED_RESOURCES";
+ public static final String KEY_TOKEN_NAMESPACE = "token:";
+ public static final String KEY_USER = "USER";
public static void setRequestTagsInContext(Map context, List tags) {
if(CollectionUtils.isEmpty(tags)) {
@@ -125,4 +127,22 @@ public static Map copyContext(Map context) {
return ret;
}
+
+ public static void setCurrentUserInContext(Map context, String user) {
+ setTokenInContext(context, KEY_USER, user);
+ }
+
+ public static String getCurrentUserFromContext(Map context) {
+ Object ret = getTokenFromContext(context, KEY_USER);
+ return ret != null ? ret.toString() : "";
+ }
+
+ public static void setTokenInContext(Map context, String tokenName, Object tokenValue) {
+ String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName;
+ context.put(tokenNameWithNamespace, tokenValue);
+ }
+ public static Object getTokenFromContext(Map context, String tokenName) {
+ String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName;
+ return MapUtils.isNotEmpty(context) ? context.get(tokenNameWithNamespace) : null;
+ }
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerPerfTracer.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerPerfTracer.java
index e130cc7ecf..4b17110dfe 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerPerfTracer.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerPerfTracer.java
@@ -71,6 +71,11 @@ public static void log(RangerPerfTracer tracer) {
}
}
+ public static void logAlways(RangerPerfTracer tracer) {
+ if(tracer != null) {
+ tracer.logAlways();
+ }
+ }
public RangerPerfTracer(Log logger, String tag, String data) {
this.logger = logger;
this.tag = tag;
@@ -96,4 +101,8 @@ public void log() {
logger.debug("[PERF] " + tag + data + ": " + elapsedTime);
}
}
+ public void logAlways() {
+ long elapsedTime = getElapsedTime();
+ logger.debug("[PERF] " + tag + data + ": " + elapsedTime);
+ }
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
index 7cfd040f24..8eb9b27e97 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
@@ -349,7 +349,7 @@ private TrustManager[] getTrustManagers() {
private SSLContext getSSLContext(KeyManager[] kmList, TrustManager[] tmList) {
try {
- if(kmList != null && tmList != null) {
+ if(tmList != null) {
SSLContext sslContext = SSLContext.getInstance(RANGER_SSL_CONTEXT_ALGO_TYPE);
sslContext.init(kmList, tmList, new SecureRandom());
@@ -360,8 +360,9 @@ private SSLContext getSSLContext(KeyManager[] kmList, TrustManager[] tmList) {
LOG.error("SSL algorithm is available in the environment", e);
} catch (KeyManagementException e) {
LOG.error("Unable to initials the SSLContext", e);
+ }catch (Exception e) {
+ LOG.error("Unable to initialize the SSLContext", e);
}
-
return null;
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRequestedResources.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRequestedResources.java
index 0f10deb698..cb3b84a0b3 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRequestedResources.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRequestedResources.java
@@ -31,6 +31,7 @@
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
@JsonAutoDetect(getterVisibility= JsonAutoDetect.Visibility.NONE, setterVisibility= JsonAutoDetect.Visibility.NONE, fieldVisibility= JsonAutoDetect.Visibility.ANY)
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL )
@@ -67,7 +68,7 @@ public void addRequestedResource(RangerAccessResource requestedResource) {
}
}
- public boolean isMutuallyExcluded(final List matchers) {
+ public boolean isMutuallyExcluded(final List matchers, final Map evalContext) {
boolean ret = true;
int matchedCount = 0;
@@ -78,7 +79,7 @@ public boolean isMutuallyExcluded(final List matche
for (RangerPolicyResourceMatcher matcher : matchers) {
- if (matcher.isMatch(resource) && matchedCount++ > 0) {
+ if (matcher.isMatch(resource, evalContext) && matchedCount++ > 0) {
ret = false;
break;
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
new file mode 100644
index 0000000000..b5c8fb07ef
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
@@ -0,0 +1,478 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.util;
+
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceEvaluator;
+import org.apache.ranger.plugin.resourcematcher.RangerAbstractResourceMatcher;
+import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+public class RangerResourceTrie {
+ private static final Log LOG = LogFactory.getLog(RangerResourceTrie.class);
+
+ private static final String DEFAULT_WILDCARD_CHARS = "*?";
+
+ private final String resourceName;
+ private final boolean optIgnoreCase;
+ private final boolean optWildcard;
+ private final String wildcardChars;
+ private final TrieNode root;
+
+ public RangerResourceTrie(RangerServiceDef.RangerResourceDef resourceDef, List evaluators) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerResourceTrie(" + resourceDef.getName() + ", evaluatorCount=" + evaluators.size() + ")");
+ }
+
+ Map matcherOptions = resourceDef.getMatcherOptions();
+
+ boolean optReplaceTokens = RangerAbstractResourceMatcher.getOptionReplaceTokens(matcherOptions);
+
+ String tokenReplaceSpecialChars = "";
+
+ if(optReplaceTokens) {
+ char delimiterStart = RangerAbstractResourceMatcher.getOptionDelimiterStart(matcherOptions);
+ char delimiterEnd = RangerAbstractResourceMatcher.getOptionDelimiterEnd(matcherOptions);
+ char delimiterEscape = RangerAbstractResourceMatcher.getOptionDelimiterEscape(matcherOptions);
+
+ tokenReplaceSpecialChars += delimiterStart;
+ tokenReplaceSpecialChars += delimiterEnd;
+ tokenReplaceSpecialChars += delimiterEscape;
+ }
+
+ this.resourceName = resourceDef.getName();
+ this.optIgnoreCase = RangerAbstractResourceMatcher.getOptionIgnoreCase(matcherOptions);
+ this.optWildcard = RangerAbstractResourceMatcher.getOptionWildCard(matcherOptions);
+ this.wildcardChars = optWildcard ? DEFAULT_WILDCARD_CHARS + tokenReplaceSpecialChars : "" + tokenReplaceSpecialChars;
+ this.root = new TrieNode(Character.valueOf((char)0));
+
+ for(T evaluator : evaluators) {
+ Map policyResources = evaluator.getPolicyResource();
+ RangerPolicyResource policyResource = policyResources != null ? policyResources.get(resourceName) : null;
+
+ if(policyResource == null) {
+ if(evaluator.getLeafResourceLevel() != null && resourceDef.getLevel() != null && evaluator.getLeafResourceLevel() < resourceDef.getLevel()) {
+ root.addWildcardEvaluator(evaluator);
+ }
+
+ continue;
+ }
+
+ if(policyResource.getIsExcludes()) {
+ root.addWildcardEvaluator(evaluator);
+ } else {
+ RangerResourceMatcher resourceMatcher = evaluator.getResourceMatcher(resourceName);
+
+ if(resourceMatcher != null && (resourceMatcher.isMatchAny())) {
+ root.addWildcardEvaluator(evaluator);
+ } else {
+ if(CollectionUtils.isNotEmpty(policyResource.getValues())) {
+ for (String resource : policyResource.getValues()) {
+ insert(resource, policyResource.getIsRecursive(), evaluator);
+ }
+ }
+ }
+ }
+ }
+
+ root.postSetup(null);
+
+ LOG.info(toString());
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerResourceTrie(" + resourceDef.getName() + ", evaluatorCount=" + evaluators.size() + "): " + toString());
+ }
+ }
+
+ public String getResourceName() {
+ return resourceName;
+ }
+
+ public List getEvaluatorsForResource(String resource) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerResourceTrie.getEvaluatorsForResource(" + resource + ")");
+ }
+
+ List ret = null;
+
+ TrieNode curr = root;
+
+ final int len = resource.length();
+ for(int i = 0; i < len; i++) {
+ Character ch = getLookupChar(resource.charAt(i));
+ TrieNode child = curr.getChild(ch);
+
+ if(child == null) {
+ ret = curr.getWildcardEvaluators();
+ curr = null; // so that curr.getEvaluators() will not be called below
+ break;
+ }
+
+ curr = child;
+ }
+
+ if(ret == null) {
+ if(curr != null) {
+ ret = curr.getEvaluators();
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerResourceTrie.getEvaluatorsForResource(" + resource + "): evaluatorCount=" + (ret == null ? 0 : ret.size()));
+ }
+
+ return ret;
+ }
+
+ public TrieData getTrieData() {
+ TrieData ret = new TrieData();
+
+ root.populateTrieData(ret);
+ ret.maxDepth = getMaxDepth();
+
+ return ret;
+ }
+
+ public int getMaxDepth() {
+ return root.getMaxDepth();
+ }
+
+ public void reorderEvaluators() {
+ root.reorderEvaluators(null);
+ }
+
+ private final Character getLookupChar(char ch) {
+ if(optIgnoreCase) {
+ ch = Character.toLowerCase(ch);
+ }
+
+ return Character.valueOf(ch);
+ }
+
+ private void insert(String resource, boolean isRecursive, T evaluator) {
+ TrieNode curr = root;
+ boolean isWildcard = false;
+
+ final int len = resource.length();
+ for(int i = 0; i < len; i++) {
+ Character ch = getLookupChar(resource.charAt(i));
+
+ if(optWildcard) {
+ if (wildcardChars.indexOf(ch) != -1) {
+ isWildcard = true;
+ break;
+ }
+ }
+
+ curr = curr.getOrCreateChild(ch);
+ }
+
+ if(isWildcard || isRecursive) {
+ curr.addWildcardEvaluator(evaluator);
+ } else {
+ curr.addEvaluator(evaluator);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ TrieData trieData = getTrieData();
+
+ sb.append("resourceName=").append(resourceName);
+ sb.append("; optIgnoreCase=").append(optIgnoreCase);
+ sb.append("; optWildcard=").append(optWildcard);
+ sb.append("; wildcardChars=").append(wildcardChars);
+ sb.append("; nodeCount=").append(trieData.nodeCount);
+ sb.append("; leafNodeCount=").append(trieData.leafNodeCount);
+ sb.append("; singleChildNodeCount=").append(trieData.singleChildNodeCount);
+ sb.append("; maxDepth=").append(trieData.maxDepth);
+ sb.append("; evaluatorListCount=").append(trieData.evaluatorListCount);
+ sb.append("; wildcardEvaluatorListCount=").append(trieData.wildcardEvaluatorListCount);
+ sb.append("; evaluatorListRefCount=").append(trieData.evaluatorListRefCount);
+ sb.append("; wildcardEvaluatorListRefCount=").append(trieData.wildcardEvaluatorListRefCount);
+
+ return sb.toString();
+ }
+
+ public class TrieData {
+ int nodeCount = 0;
+ int leafNodeCount = 0;
+ int singleChildNodeCount = 0;
+ int maxDepth = 0;
+ int evaluatorListCount = 0;
+ int wildcardEvaluatorListCount = 0;
+ int evaluatorListRefCount = 0;
+ int wildcardEvaluatorListRefCount = 0;
+ }
+}
+
+class TrieNode