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 <mad...@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 <akulka...@hortonworks.com>
Authored: Wed Oct 19 13:52:48 2016 -0700
Committer: Madhan Neethiraj <mad...@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);
        }
 }

Reply via email to