You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2016/11/02 17:25:14 UTC

incubator-ranger git commit: RANGER-1200: Ranger policies should support notion of OWNER user

Repository: incubator-ranger
Updated Branches:
  refs/heads/master efbed804f -> 91f270cfd


RANGER-1200: Ranger policies should support notion of OWNER user

Signed-off-by: Madhan Neethiraj <ma...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/91f270cf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/91f270cf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/91f270cf

Branch: refs/heads/master
Commit: 91f270cfd86e2dcc53f29979bd55cad97b87e45a
Parents: efbed80
Author: Abhay Kulkarni <ak...@hortonworks.com>
Authored: Wed Oct 19 13:52:48 2016 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Wed Nov 2 10:24:59 2016 -0700

----------------------------------------------------------------------
 .../plugin/policyengine/RangerPolicyEngine.java |   1 +
 .../RangerDefaultPolicyItemEvaluator.java       |  33 ++++-
 .../RangerOptimizedPolicyEvaluator.java         |  27 +++-
 .../plugin/policyengine/TestPolicyEngine.java   |   7 +
 .../policyengine/test_policyengine_owner.json   | 147 +++++++++++++++++++
 .../org/apache/ranger/biz/ServiceDBStore.java   |   9 +-
 6 files changed, 219 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/91f270cf/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
index e0a8a91..06c7d16 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
@@ -39,6 +39,7 @@ public interface RangerPolicyEngine {
 	String AUDIT_DEFAULT = "audit-default";
 
 	String USER_CURRENT = "{" + RangerAccessRequestUtil.KEY_USER + "}";
+	String RESOURCE_OWNER = "{OWNER}";
 
 	String getServiceName();
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/91f270cf/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
----------------------------------------------------------------------
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 84aac1e..6119dbc 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
@@ -36,6 +36,7 @@ import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
@@ -50,6 +51,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv
 	private static final Log PERF_POLICYCONDITION_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policycondition.request");
 
 	private boolean hasCurrentUser = false;
+	private boolean hasResourceOwner = false;
 
 	public RangerDefaultPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, int policyItemType, int policyItemIndex, RangerPolicyEngineOptions options) {
 		super(serviceDef, policy, policyItem, policyItemType, policyItemIndex, options);
@@ -105,6 +107,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv
 
 		List<String> users = policyItem != null ? policyItem.getUsers() : null;
 		this.hasCurrentUser = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.USER_CURRENT);
+		this.hasResourceOwner = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.RESOURCE_OWNER);
 
 		if(LOG.isDebugEnabled()) {
 			LOG.debug("<== RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", conditionsCount=" + getConditionEvaluators().size() + ")");
@@ -126,7 +129,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv
 		}
 
 		if(policyItem != null) {
-			if(matchUserGroup(request.getUser(), request.getUserGroups())) {
+			if(matchUserGroupAndOwner(request)) {
 				if (request.isAccessTypeDelegatedAdmin()) { // used only in grant/revoke scenario
 					if (policyItem.getDelegateAdmin()) {
 						ret = true;
@@ -194,6 +197,34 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv
 		return ret;
 	}
 
+	private boolean matchUserGroupAndOwner(RangerAccessRequest request) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchUserGroupAndOwner(" + request + ")");
+		}
+
+		boolean ret = false;
+
+		String user = request.getUser();
+		Set<String> userGroups = request.getUserGroups();
+
+		if (hasResourceOwner) {
+			RangerAccessResource accessedResource = request.getResource();
+			String resourceOwner = accessedResource != null ? accessedResource.getOwnerUser() : null;
+
+			if (user != null && resourceOwner != null && user.equals(resourceOwner)) {
+				ret = true;
+			}
+		}
+		if (!ret) {
+			ret = matchUserGroup(user, userGroups);
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchUserGroupAndOwner(" + request + "): " + ret);
+		}
+
+		return ret;
+	}
 	@Override
 	public boolean matchAccessType(String accessType) {
 		if(LOG.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/91f270cf/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
----------------------------------------------------------------------
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 fb854d0..1fcd08e 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
@@ -26,6 +26,7 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
 
@@ -41,6 +42,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
     private boolean     hasAllPerms    = false;
     private boolean     hasPublicGroup = false;
     private boolean     hasCurrentUser = false;
+    private boolean     hasResourceOwner = false;
 
     // For computation of priority
     private static final String RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING   = "*";
@@ -78,8 +80,13 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
         hasAllPerms = checkIfHasAllPerms();
 
         for (String user : users) {
-            if (user.equalsIgnoreCase(RangerPolicyEngine.USER_CURRENT)) {
+            if (!hasCurrentUser && user.equalsIgnoreCase(RangerPolicyEngine.USER_CURRENT)) {
                 hasCurrentUser = true;
+            }
+            if (!hasResourceOwner && user.equalsIgnoreCase(RangerPolicyEngine.RESOURCE_OWNER)) {
+                hasResourceOwner = true;
+            }
+            if (hasCurrentUser && hasResourceOwner) {
                 break;
             }
         }
@@ -238,7 +245,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
     protected boolean hasMatchablePolicyItem(RangerAccessRequest request) {
         boolean ret = false;
 
-        if (hasPublicGroup || hasCurrentUser || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups())) {
+        if (hasPublicGroup || hasCurrentUser || isOwnerMatch(request) || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups())) {
             if(request.isAccessTypeDelegatedAdmin()) {
                 ret = delegateAdmin;
             } else if(hasAllPerms) {
@@ -251,6 +258,22 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
         return ret;
     }
 
+    private boolean isOwnerMatch(RangerAccessRequest request) {
+        boolean ret = false;
+
+        if (hasResourceOwner) {
+            RangerAccessResource accessedResource = request.getResource();
+            String resourceOwner = accessedResource != null ? accessedResource.getOwnerUser() : null;
+            String user = request.getUser();
+
+            if (user != null && resourceOwner != null && user.equals(resourceOwner)) {
+                ret = true;
+            }
+        }
+
+        return ret;
+    }
+
     private boolean hasMatchablePolicyItem(String user, Set<String> userGroups, String accessType) {
         boolean ret = false;
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/91f270cf/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
index cb0af84..2ae280d 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
@@ -256,6 +256,13 @@ public class TestPolicyEngine {
 		runTestsFromResourceFiles(resourceFiles);
 	}
 
+	@Test
+	public void testPolicyEngine_owner() {
+		String[] resourceFiles = {"/policyengine/test_policyengine_owner.json"};
+
+		runTestsFromResourceFiles(resourceFiles);
+	}
+
 	private void runTestsFromResourceFiles(String[] resourceNames) {
 		for(String resourceName : resourceNames) {
 			InputStream inStream = this.getClass().getResourceAsStream(resourceName);

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/91f270cf/agents-common/src/test/resources/policyengine/test_policyengine_owner.json
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_owner.json b/agents-common/src/test/resources/policyengine/test_policyengine_owner.json
new file mode 100644
index 0000000..82a6632
--- /dev/null
+++ b/agents-common/src/test/resources/policyengine/test_policyengine_owner.json
@@ -0,0 +1,147 @@
+{
+  "serviceName":"hdfsdev",
+
+  "serviceDef":{
+    "name":"hdfs",
+    "id":1,
+    "resources":[
+    {"name":"path","type":"path","level":1,"mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Resource Path","description":"HDFS file or directory path"}
+    ],
+    "accessTypes":[
+      {"name":"read","label":"Read"},
+      {"name":"write","label":"Write"},
+      {"name":"execute","label":"Execute"}
+    ],
+    "contextEnrichers": [ ],
+    "policyConditions": [
+      {
+        "itemId":1,
+        "name":"ScriptConditionEvaluator",
+        "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator",
+        "evaluatorOptions" : {"engineName":"JavaScript"},
+        "label":"Script",
+        "description": "Script to execute"
+      }
+    ]
+  },
+
+  "policies":[
+    {"id":1,"name":"allow-all-to-owner under /public/{USER}","isEnabled":true,"isAuditEnabled":true,
+     "resources":{"path":{"values":["/public/{USER}"],"isRecursive":true}},
+     "policyItems":[
+       {"accesses":[{"type":"read","isAllowed":true},{"type":"write", "isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["{OWNER}"],"groups":[],"delegateAdmin":false}
+     ]
+    }
+    ,
+    {"id":2,"name":"allow-all-to-owner under /finance/restricted/*","isEnabled":true,"isAuditEnabled":true,
+      "resources":{"path":{"values":["/finance/restricted/*"],"isRecursive":true}},
+      "policyItems":[
+        {"accesses":[{"type":"read","isAllowed":true},{"type":"write", "isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["{OWNER}"],"groups":[],"delegateAdmin":false}
+        ,
+        {"accesses":[{"type":"read","isAllowed":true}],"users":[],"groups":["finance"],"delegateAdmin":false}
+
+      ]
+    }
+    ,
+    {"id":3,"name":"allow-read-to-non-owner under /public/partners/*","isEnabled":true,"isAuditEnabled":true,
+      "resources":{"path":{"values":["/public/partners/*"],"isRecursive":true}},
+      "policyItems":[
+        {"accesses":[{"type":"read","isAllowed":true},{"type":"write", "isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["{OWNER}"],"groups":[],"delegateAdmin":false}
+      ,
+        {"accesses":[{"type":"read","isAllowed":true}],"users":[],"groups":["employees"],"delegateAdmin":false}
+
+      ]
+    }
+  ],
+
+  "tests":[
+    {"name":"ALLOW 'read /public/user1/tax.db' for user=user1, owner=user1; ",
+     "request":{
+      "resource":{"elements":{"path":"/public/user1/tax.db"}, "ownerUser":"user1"},
+      "accessType":"read","user":"user1","userGroups":[],"requestData":"read /public/user1/tax.db, user=user1, owner=user1"
+     },
+     "result":{"isAudited":true,"isAllowed":true,"policyId":1}
+    }
+    ,
+
+    {"name":"DENY 'read /public/user1/tax.db' for user=user1, owner=user2; ",
+     "request":{
+      "resource":{"elements":{"path":"/public/user1/tax.db"}, "ownerUser":"user2"},
+      "accessType":"read","user":"user1","userGroups":[],"requestData":"read /public/user1/tax.db, user=user1, owner=user2"
+     },
+     "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+    }
+    ,
+    {"name":"DENY 'read /public/user2/tax.db' for user=user2, owner=user1; ",
+      "request":{
+        "resource":{"elements":{"path":"/public/user2/tax.db"}, "ownerUser":"user1"},
+        "accessType":"read","user":"user2","userGroups":[],"requestData":"read /public/user1/tax.db, user=user2, owner=user1"
+      },
+      "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+    }
+    ,
+    {"name":"ALLOW 'read /finance/restricted/sales.db' for user=finadmin, owner=finadmin; ",
+      "request":{
+        "resource":{"elements":{"path":"/finance/restricted/sales.db"}, "ownerUser":"finadmin"},
+        "accessType":"read","user":"finadmin","userGroups":[],"requestData":"read /finance/restricted/sales.db, user=finadmin, owner=finadmin"
+      },
+      "result":{"isAudited":true,"isAllowed":true,"policyId":2}
+    }
+    ,
+    {"name":"ALLOW 'read /finance/restricted/sales.db' for user=user1, group=finance; ",
+      "request":{
+        "resource":{"elements":{"path":"/finance/restricted/sales.db"}, "ownerUser":"finadmin"},
+        "accessType":"read","user":"user1","userGroups":["finance"],"requestData":"read /finance/restricted/sales.db, user=user1, group=finance"
+      },
+      "result":{"isAudited":true,"isAllowed":true,"policyId":2}
+    }
+    ,
+    {"name":"DENY 'write /finance/restricted/sales.db' for user=user1, group=finance; ",
+      "request":{
+        "resource":{"elements":{"path":"/finance/restricted/sales.db"}, "ownerUser":"finadmin"},
+        "accessType":"write","user":"user1","userGroups":["finance"],"requestData":"write /finance/restricted/sales.db, user=user1, group=finance"
+      },
+      "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+    }
+    ,
+    {"name":"ALLOW 'read /finance/restricted/sales.db' for user=user1, group=finance; ",
+      "request":{
+        "resource":{"elements":{"path":"/finance/restricted/sales.db"}},
+        "accessType":"read","user":"user1","userGroups":["finance"],"requestData":"read /finance/restricted/sales.db, user=user1, group=finance"
+      },
+      "result":{"isAudited":true,"isAllowed":true,"policyId":2}
+    }
+    ,
+    {"name":"DENY 'write /finance/restricted/sales.db' for user=user1, group=finance; ",
+      "request":{
+        "resource":{"elements":{"path":"/finance/restricted/sales.db"}},
+        "accessType":"write","user":"user1","userGroups":["finance"],"requestData":"write /finance/restricted/sales.db, user=user1, group=finance"
+      },
+      "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+    }
+    ,
+    {"name":"DENY 'write /public/partners/vendors.db' for user=user1, group=employees; ",
+      "request":{
+        "resource":{"elements":{"path":"/public/partners/vendors.db"}},
+        "accessType":"write","user":"user1","userGroups":["employees"],"requestData":"write /public/partners/vendors.db, user=user1, group=employees"
+      },
+      "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+    }
+    ,
+    {"name":"ALLOW 'read /public/partners/vendors.db' for user=user1, group=employees; ",
+      "request":{
+        "resource":{"elements":{"path":"/public/partners/vendors.db"}},
+        "accessType":"read","user":"user1","userGroups":["employees"],"requestData":"read /public/partners/vendors.db, user=user1, group=employees"
+      },
+      "result":{"isAudited":true,"isAllowed":true,"policyId":3}
+    }
+  ,
+    {"name":"ALLOW 'write /public/partners/vendors.db' for user=user1, group=employees; owner=user1",
+      "request":{
+        "resource":{"elements":{"path":"/public/partners/vendors.db"}, "ownerUser":"user1"},
+        "accessType":"read","user":"user1","userGroups":["employees"],"requestData":"write /public/partners/vendors.db, user=user1, group=employees; owner=user1"
+      },
+      "result":{"isAudited":true,"isAllowed":true,"policyId":3}
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/91f270cf/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
index b6b2dc5..3841785 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
@@ -284,7 +284,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 							public Object doInTransaction(TransactionStatus status) {
 								EmbeddedServiceDefsUtil.instance().init(dbStore);
 								getServiceUpgraded();
-								createGenericUser();
+								createGenericUsers();
 								return null;
 							}
 						});
@@ -3833,10 +3833,15 @@ public class ServiceDBStore extends AbstractServiceStore {
 		return RangerPolicyEngine.AUDIT_DEFAULT;
 	}
 
-	private void createGenericUser() {
+	private void createGenericUsers() {
 		VXUser genericUser = new VXUser();
+
 		genericUser.setName(RangerPolicyEngine.USER_CURRENT);
 		genericUser.setDescription(RangerPolicyEngine.USER_CURRENT);
 		xUserService.createXUserWithOutLogin(genericUser);
+
+		genericUser.setName(RangerPolicyEngine.RESOURCE_OWNER);
+		genericUser.setDescription(RangerPolicyEngine.RESOURCE_OWNER);
+		xUserService.createXUserWithOutLogin(genericUser);
 	}
 }