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); } }