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 2015/03/14 19:52:25 UTC
[1/4] incubator-ranger git commit: RANGER-278 move validation classes
under org.apache.ranger.plugin.model.validation
Repository: incubator-ranger
Updated Branches:
refs/heads/master 9b3597617 -> 7bb686873
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
deleted file mode 100644
index 2fb82ce..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
+++ /dev/null
@@ -1,524 +0,0 @@
-package org.apache.ranger.rest;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.ranger.plugin.model.RangerPolicy;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.plugin.util.SearchFilter;
-import org.apache.ranger.rest.RangerPolicyValidator;
-import org.apache.ranger.rest.ValidationFailureDetails;
-import org.apache.ranger.rest.RangerValidator.Action;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Sets;
-
-public class TestRangerPolicyValidator {
-
- @Before
- public void setUp() throws Exception {
- _store = mock(ServiceStore.class);
- _policy = mock(RangerPolicy.class);
- _validator = new RangerPolicyValidator(_store);
- _serviceDef = mock(RangerServiceDef.class);
- }
-
- final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
- final Object[] policyItemsData = new Object[] {
- ImmutableMap.of( // all good
- "users", new String[] {"user1" ," user2"},
- "groups", new String[] {"group1", "group2"},
- "accesses", new String[] { "r", "w" },
- "isAllowed", new Boolean[] { true, true }),
- ImmutableMap.of( // no users, access type different case
- "groups", new String[] {"group3", "group4"},
- "accesses", new String[]{"W", "x"},
- "isAllowed", new Boolean[] { true, true }),
- ImmutableMap.of( // no groups
- "users", new String[] {"user3" ," user4"},
- "accesses", new String[] { "r", "x" },
- "isAllowed", new Boolean[] { true, true }),
- ImmutableMap.of( // isallowed on access types is null, case is different from that in definition
- "users", new String[] {"user7" ," user6"},
- "accesses", new String[] { "a" },
- "isAllowed", new Boolean[] { null, null })
- };
- String[] accessTypes = new String[] { "r", "w", "x", "A" }; // mix of lower and upper case
- String[] accessTypes_bad = new String[] { "r", "w", "xx", }; // two missing (x, a), one new that isn't on bad (xx)
-
- private final Object[][] resourceDefData = new Object[][] {
- // { name, mandatory, reg-exp, excludesSupported, recursiveSupported }
- { "db", true, "db\\d+", null, null }, // valid values: db1, db22, db983, etc.; invalid: db, db12x, ttx11, etc.; null => false for excludes and recursive
- { "tbl", true, null, true, true }, // regex == null => anything goes; excludes == true, recursive == true
- { "col", false, "col\\d{1,2}", false, true } // valid: col1, col47, etc.; invalid: col, col238, col1, etc., excludes == false, recursive == true
- };
-
- private final Object[][] policyResourceMap_good = new Object[][] {
- // resource-name, values, excludes, recursive
- { "db", new String[] { "db1", "db2" }, null, null },
- { "TBL", new String[] { "tbl1", "tbl2" }, true, false } // case should not matter
- };
-
- private final Object[][] policyResourceMap_bad = new Object[][] {
- // resource-name, values, excludes, recursive
- { "db", new String[] { "db1", "db2" }, null, true }, // mandatory "tbl" missing; recursive==true specified when resource-def does not support it (null)
- {"col", new String[] { "col12", "col 1" }, true, true }, // wrong format of value for "col"; excludes==true specified when resource-def does not allow it (false)
- {"extra", new String[] { "extra1", "extra2" }, null, null } // spurious "extra" specified
- };
-
- @Test
- public final void testIsValid_long() throws Exception {
- // this validation should be removed if we start supporting other than delete action
- assertFalse(_validator.isValid(3L, Action.CREATE, _failures));
- _utils.checkFailureForInternalError(_failures);
-
- // should fail with appropriate error message if id is null
- _failures.clear(); _failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
- _utils.checkFailureForMissingValue(_failures, "id");
-
- // should fail with appropriate error message if policy can't be found for the specified id
- when(_store.getPolicy(1L)).thenReturn(null);
- when(_store.getPolicy(2L)).thenThrow(new Exception());
- RangerPolicy existingPolicy = mock(RangerPolicy.class);
- when(_store.getPolicy(3L)).thenReturn(existingPolicy);
- _failures.clear(); assertFalse(_validator.isValid(1L, Action.DELETE, _failures));
- _utils.checkFailureForSemanticError(_failures, "id");
- _failures.clear(); assertFalse(_validator.isValid(2L, Action.DELETE, _failures));
- _utils.checkFailureForSemanticError(_failures, "id");
-
- // if policy exists then delete validation should pass
- assertTrue(_validator.isValid(3L, Action.DELETE, _failures));
- }
-
- @Test
- public final void testIsValid_happyPath() throws Exception {
- // valid policy has valid non-empty name and service name
- when(_policy.getService()).thenReturn("service-name");
- // service name exists
- RangerService service = mock(RangerService.class);
- when(service.getType()).thenReturn("service-type");
- when(_store.getServiceByName("service-name")).thenReturn(service);
- // service points to a valid service-def
- _serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes);
- when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
- // a matching policy should exist for create when checked by id and not exist when checked by name.
- when(_store.getPolicy(7L)).thenReturn(null);
- RangerPolicy existingPolicy = mock(RangerPolicy.class);
- when(existingPolicy.getId()).thenReturn(8L);
- when(_store.getPolicy(8L)).thenReturn(existingPolicy);
- SearchFilter createFilter = new SearchFilter();
- createFilter.setParam(SearchFilter.POLICY_NAME, "service-type");
- createFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-1"); // this name would be used for create
- when(_store.getPolicies(createFilter)).thenReturn(new ArrayList<RangerPolicy>());
- // a matching policy should not exist for update.
- SearchFilter updateFilter = new SearchFilter();
- updateFilter.setParam(SearchFilter.POLICY_NAME, "service-type");
- updateFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-2"); // this name would be used for update
- List<RangerPolicy> existingPolicies = new ArrayList<RangerPolicy>();
- existingPolicies.add(existingPolicy);
- when(_store.getPolicies(updateFilter)).thenReturn(existingPolicies);
- // valid policy can have empty set of policy items if audit is turned on
- // null value for audit is treated as audit on.
- for (Action action : cu) {
- for (Boolean auditEnabled : new Boolean[] { null, true } ) {
- when(_policy.getIsAuditEnabled()).thenReturn(auditEnabled);
- if (action == Action.CREATE) {
- when(_policy.getId()).thenReturn(7L);
- when(_policy.getName()).thenReturn("policy-name-1");
- assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
- assertTrue(_failures.isEmpty());
- } else {
- // update should work both when by-name is found or not, since nothing found by-name means name is being updated.
- when(_policy.getId()).thenReturn(8L);
- when(_policy.getName()).thenReturn("policy-name-1");
- assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
- assertTrue(_failures.isEmpty());
-
- when(_policy.getName()).thenReturn("policy-name-2");
- assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
- assertTrue(_failures.isEmpty());
- }
- }
- }
- // if audit is disabled then policy should have policy items and all of them should be valid
- List<RangerPolicyItem> policyItems = _utils.createPolicyItems(policyItemsData);
- when(_policy.getPolicyItems()).thenReturn(policyItems);
- when(_policy.getIsAuditEnabled()).thenReturn(false);
- for (Action action : cu) {
- if (action == Action.CREATE) {
- when(_policy.getId()).thenReturn(7L);
- when(_policy.getName()).thenReturn("policy-name-1");
- } else {
- when(_policy.getId()).thenReturn(8L);
- when(_policy.getName()).thenReturn("policy-name-2");
- }
- assertTrue("" + action , _validator.isValid(_policy, action, _failures));
- assertTrue(_failures.isEmpty());
- }
-
- // above succeeded as service def did not have any resources on it, mandatory or otherwise.
- // policy should have all mandatory resources specified, and they should conform to the validation pattern in resource definition
- List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
- when(_serviceDef.getResources()).thenReturn(resourceDefs);
- Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap(policyResourceMap_good);
- when(_policy.getResources()).thenReturn(resourceMap);
-
- for (Action action : cu) {
- if (action == Action.CREATE) {
- when(_policy.getId()).thenReturn(7L);
- when(_policy.getName()).thenReturn("policy-name-1");
- } else {
- when(_policy.getId()).thenReturn(8L);
- when(_policy.getName()).thenReturn("policy-name-2");
- }
- assertTrue("" + action , _validator.isValid(_policy, action, _failures));
- assertTrue(_failures.isEmpty());
- }
- }
-
- void checkFailure_isValid(Action action, String errorType, String field) {
- checkFailure_isValid(action, errorType, field, null);
- }
-
- void checkFailure_isValid(Action action, String errorType, String field, String subField) {
- _failures.clear();
- assertFalse(_validator.isValid(_policy, action, _failures));
- switch (errorType) {
- case "missing":
- _utils.checkFailureForMissingValue(_failures, field, subField);
- break;
- case "semantic":
- _utils.checkFailureForSemanticError(_failures, field, subField);
- break;
- case "internal error":
- _utils.checkFailureForInternalError(_failures);
- break;
- default:
- fail("Unsupported errorType[" + errorType + "]");
- break;
- }
- }
-
- @Test
- public final void testIsValid_failures() throws Exception {
- for (Action action : cu) {
- // passing in a null policy should fail with appropriate failure reason
- _policy = null;
- checkFailure_isValid(action, "missing", "policy");
-
- // policy must have a name on it
- _policy = mock(RangerPolicy.class);
- for (String name : new String[] { null, " " }) {
- when(_policy.getName()).thenReturn(name);
- checkFailure_isValid(action, "missing", "name");
- }
-
- // for update id is required!
- if (action == Action.UPDATE) {
- when(_policy.getId()).thenReturn(null);
- checkFailure_isValid(action, "missing", "id");
- }
- }
- /*
- * Id is ignored for Create but name should not belong to an existing policy. For update, policy should exist for its id and should match its name.
- */
- when(_policy.getName()).thenReturn("policy-name");
- when(_policy.getService()).thenReturn("service-name");
-
- RangerPolicy existingPolicy = mock(RangerPolicy.class);
- when(existingPolicy.getId()).thenReturn(7L);
- List<RangerPolicy> existingPolicies = new ArrayList<RangerPolicy>();
- existingPolicies.add(existingPolicy);
- SearchFilter filter = new SearchFilter();
- filter.setParam(SearchFilter.SERVICE_NAME, "service-name");
- filter.setParam(SearchFilter.POLICY_NAME, "policy-name");
- when(_store.getPolicies(filter)).thenReturn(existingPolicies);
- checkFailure_isValid(Action.CREATE, "semantic", "name");
-
- // update : does not exist for id
- when(_policy.getId()).thenReturn(7L);
- when(_store.getPolicy(7L)).thenReturn(null);
- checkFailure_isValid(Action.UPDATE, "semantic", "id");
-
- // Update: name should not point to an existing different policy, i.e. with a different id
- when(_store.getPolicy(7L)).thenReturn(existingPolicy);
- RangerPolicy anotherExistingPolicy = mock(RangerPolicy.class);
- when(anotherExistingPolicy.getId()).thenReturn(8L);
- existingPolicies.clear();
- existingPolicies.add(anotherExistingPolicy);
- when(_store.getPolicies(filter)).thenReturn(existingPolicies);
- checkFailure_isValid(Action.UPDATE, "semantic", "id/name");
-
- // more than one policies with same name is also an internal error
- when(_policy.getName()).thenReturn("policy-name");
- when(_store.getPolicies(filter)).thenReturn(existingPolicies);
- existingPolicies.add(existingPolicy);
- existingPolicy = mock(RangerPolicy.class);
- existingPolicies.add(existingPolicy);
- _failures.clear(); assertFalse(_validator.isValid(_policy, Action.UPDATE, _failures));
- _utils.checkFailureForInternalError(_failures);
-
- // policy must have service name on it and it should be valid
- when(_policy.getName()).thenReturn("policy-name");
- when(_store.getServiceByName("service-name")).thenReturn(null);
- when(_store.getServiceByName("another-service-name")).thenThrow(new Exception());
-
- for (Action action : cu) {
- when(_policy.getService()).thenReturn("service-name");
- _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
- _utils.checkFailureForMissingValue(_failures, "service");
-
- when(_policy.getService()).thenReturn("another-service-name");
- _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
- _utils.checkFailureForMissingValue(_failures, "service");
- }
-
- // policy must contain at least one policy item
- List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicy.RangerPolicyItem>();
- when(_policy.getService()).thenReturn("service-name");
- RangerService service = mock(RangerService.class);
- when(_store.getServiceByName("service-name")).thenReturn(service);
- for (Action action : cu) {
- // when it is null
- when(_policy.getPolicyItems()).thenReturn(null);
- _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
- _utils.checkFailureForMissingValue(_failures, "policy items");
- // or when it is not null but empty.
- when(_policy.getPolicyItems()).thenReturn(policyItems);
- _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
- _utils.checkFailureForMissingValue(_failures, "policy items");
- }
-
- // these are known good policy items -- same as used above in happypath
- policyItems = _utils.createPolicyItems(policyItemsData);
- when(_policy.getPolicyItems()).thenReturn(policyItems);
- // policy item check requires that service def should exist
- when(service.getType()).thenReturn("service-type");
- when(_store.getServiceDefByName("service-type")).thenReturn(null);
- for (Action action : cu) {
- _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
- _utils.checkFailureForInternalError(_failures, "policy service def");
- }
-
- // service-def should contain the right access types on it.
- _serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes_bad);
- when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
- for (Action action : cu) {
- _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
- _utils.checkFailureForSemanticError(_failures, "policy item access type");
- }
-
- // create the right service def with right resource defs - this is the same as in the happypath test above.
- _serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes);
- when(_store.getPolicies(filter)).thenReturn(null);
- List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
- when(_serviceDef.getResources()).thenReturn(resourceDefs);
- when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
- // one mandtory is missing (tbl) and one unknown resource is specified (extra), and values of option resource don't conform to validation pattern (col)
- Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
- when(_policy.getResources()).thenReturn(policyResources);
- for (Action action : cu) {
- _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
- _utils.checkFailureForMissingValue(_failures, "resources", "tbl"); // for missing resource: tbl
- _utils.checkFailureForSemanticError(_failures, "resources", "extra"); // for spurious resource: "extra"
- _utils.checkFailureForSemanticError(_failures, "resource-values", "col"); // for spurious resource: "extra"
- _utils.checkFailureForSemanticError(_failures, "isRecursive", "db"); // for specifying it as true when def did not allow it
- _utils.checkFailureForSemanticError(_failures, "isExcludes", "col"); // for specifying it as true when def did not allow it
- }
- }
-
- @Test
- public void test_isValidResourceValues() {
- List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
- when(_serviceDef.getResources()).thenReturn(resourceDefs);
- Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
- assertFalse(_validator.isValidResourceValues(policyResources, _failures, _serviceDef));
- _utils.checkFailureForSemanticError(_failures, "resource-values", "col");
-
- policyResources = _utils.createPolicyResourceMap(policyResourceMap_good);
- assertTrue(_validator.isValidResourceValues(policyResources, _failures, _serviceDef));
- }
-
- @Test
- public void test_isValidPolicyItems_failures() {
- // null/empty list is good because there is nothing
- assertTrue(_validator.isValidPolicyItems(null, _failures, _serviceDef));
- _failures.isEmpty();
-
- List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicy.RangerPolicyItem>();
- assertTrue(_validator.isValidPolicyItems(policyItems, _failures, _serviceDef));
- _failures.isEmpty();
-
- // null elements in the list are flagged
- policyItems.add(null);
- assertFalse(_validator.isValidPolicyItems(policyItems, _failures, _serviceDef));
- _utils.checkFailureForMissingValue(_failures, "policy item");
- }
-
- @Test
- public void test_isValidPolicyItem_failures() {
-
- // empty access collections are invalid
- RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
- when(policyItem.getAccesses()).thenReturn(null);
- _failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
- _utils.checkFailureForMissingValue(_failures, "policy item accesses");
-
- List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicy.RangerPolicyItemAccess>();
- when(policyItem.getAccesses()).thenReturn(accesses);
- _failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
- _utils.checkFailureForMissingValue(_failures, "policy item accesses");
-
- // both user and groups can't be null
- RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
- accesses.add(access);
- when(policyItem.getUsers()).thenReturn(null);
- when(policyItem.getGroups()).thenReturn(new ArrayList<String>());
- _failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
- _utils.checkFailureForMissingValue(_failures, "policy item users/user-groups");
- }
-
- @Test
- public void test_isValidItemAccesses_happyPath() {
-
- // happy path
- Object[][] data = new Object[][] {
- { "a", null }, // valid
- { "b", true }, // valid
- { "c", true }, // valid
- };
- List<RangerPolicyItemAccess> accesses = _utils.createItemAccess(data);
- _serviceDef = _utils.createServiceDefWithAccessTypes(new String[] { "a", "b", "c", "d" });
- assertTrue(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
- assertTrue(_failures.isEmpty());
- }
-
- @Test
- public void test_isValidItemAccesses_failure() {
-
- // null policy item access values are an error
- List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicyItemAccess>();
- accesses.add(null);
- _failures.clear(); assertFalse(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
- _utils.checkFailureForMissingValue(_failures, "policy item access");
-
- // all items must be valid for this call to be valid
- Object[][] data = new Object[][] {
- { "a", null }, // valid
- { null, null }, // invalid - name can't be null
- { "c", true }, // valid
- };
- accesses = _utils.createItemAccess(data);
- _serviceDef = _utils.createServiceDefWithAccessTypes(new String[] { "a", "b", "c", "d" });
- _failures.clear(); assertFalse(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
- }
-
- @Test
- public void test_isValidPolicyItemAccess_happyPath() {
-
- RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
- when(access.getType()).thenReturn("an-Access"); // valid
-
- Set<String> validAccesses = Sets.newHashSet(new String[] { "an-access", "another-access" }); // valid accesses should be lower-cased
-
- // both null or true access types are the same and valid
- for (Boolean allowed : new Boolean[] { null, true } ) {
- when(access.getIsAllowed()).thenReturn(allowed);
- assertTrue(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
- assertTrue(_failures.isEmpty());
- }
- }
-
- @Test
- public void test_isValidPolicyItemAccess_failures() {
-
- Set<String> validAccesses = Sets.newHashSet(new String[] { "anAccess", "anotherAccess" });
- // null/empty names are invalid
- RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
- when(access.getIsAllowed()).thenReturn(null); // valid since null == true
- for (String type : new String[] { null, " "}) {
- when(access.getType()).thenReturn(type); // invalid
- // null/empty validAccess set skips all checks
- assertTrue(_validator.isValidPolicyItemAccess(access, _failures, null));
- assertTrue(_validator.isValidPolicyItemAccess(access, _failures, new HashSet<String>()));
- _failures.clear(); assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
- _utils.checkFailureForMissingValue(_failures, "policy item access type");
- }
-
- when(access.getType()).thenReturn("anAccess"); // valid
- when(access.getIsAllowed()).thenReturn(false); // invalid
- _failures.clear();assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
- _utils.checkFailureForSemanticError(_failures, "policy item access type allowed");
-
- when(access.getType()).thenReturn("newAccessType"); // invalid
- _failures.clear(); assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
- _utils.checkFailureForSemanticError(_failures, "policy item access type");
- }
-
- final Object[][] resourceDef_happyPath = new Object[][] {
- // { "resource-name", "isExcludes", "isRecursive" }
- { "db", true, true },
- { "tbl", null, true },
- { "col", true, false },
- };
-
- private Object[][] policyResourceMap_happyPath = new Object[][] {
- // { "resource-name", "isExcludes", "isRecursive" }
- { "db", null, true }, // null should be treated as false
- { "tbl", false, false }, // set to false where def is null and def is true
- { "col", true, null} // set to null where def is false
- };
-
- @Test
- public final void test_isValidResourceFlags_happyPath() {
- // passing null values effectively bypasses the filter
- assertTrue(_validator.isValidResourceFlags(null, _failures, null, "a-service-def", "a-policy"));
- // so does passing in empty collections
- Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap2(policyResourceMap_happyPath);
- List<RangerResourceDef> resourceDefs = _utils.createResourceDefs2(resourceDef_happyPath);
- when(_serviceDef.getResources()).thenReturn(resourceDefs);
- assertTrue(_validator.isValidResourceFlags(resourceMap, _failures, resourceDefs, "a-service-def", "a-policy"));
- }
-
- private Object[][] policyResourceMap_failures = new Object[][] {
- // { "resource-name", "isExcludes", "isRecursive" }
- { "db", true, true }, // ok: def has true for both
- { "tbl", true, null }, // excludes: def==false, policy==true
- { "col", false, true } // recursive: def==null (i.e. false), policy==true
- };
-
- @Test
- public final void test_isValidResourceFlags_failures() {
- // passing true when def says false/null
- List<RangerResourceDef> resourceDefs = _utils.createResourceDefs2(resourceDef_happyPath);
- Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap2(policyResourceMap_failures);
- when(_serviceDef.getResources()).thenReturn(resourceDefs);
- assertFalse(_validator.isValidResourceFlags(resourceMap, _failures, resourceDefs, "a-service-def", "a-policy"));
- _utils.checkFailureForSemanticError(_failures, "isExcludes", "tbl");
- _utils.checkFailureForSemanticError(_failures, "isRecursive", "col");
- }
-
- private ValidationTestUtils _utils = new ValidationTestUtils();
- private List<ValidationFailureDetails> _failures = new ArrayList<ValidationFailureDetails>();
- private ServiceStore _store;
- private RangerPolicy _policy;
- private RangerPolicyValidator _validator;
- private RangerServiceDef _serviceDef;
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
deleted file mode 100644
index 8702509..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
+++ /dev/null
@@ -1,355 +0,0 @@
-package org.apache.ranger.rest;
-
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.rest.RangerServiceDefValidator;
-import org.apache.ranger.rest.ValidationFailureDetails;
-import org.apache.ranger.rest.RangerValidator.Action;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.collect.ImmutableMap;
-
-public class TestRangerServiceDefValidator {
-
- @Before
- public void setUp() throws Exception {
- _store = mock(ServiceStore.class);
- _validator = new RangerServiceDefValidator(_store);
- _failures = new ArrayList<ValidationFailureDetails>();
- _serviceDef = mock(RangerServiceDef.class);
- }
-
- final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
-
- final Object[][] accessTypes_good = new Object[][] {
- { "read", null }, // ok, null implied grants
- { "write", new String[] { } }, // ok, empty implied grants
- { "admin", new String[] { "READ", "write" } } // ok, admin access implies read/write, access types are case-insensitive
- };
-
- final Map<String, String[]> enums_good = ImmutableMap.of(
- "authentication-type", new String[] { "simple", "kerberos" },
- "time-unit", new String[] { "day", "hour", "minute" }
- );
-
- @Test
- public final void test_isValid_happyPath_create() throws Exception {
-
- // setup access types with implied access and couple of enums
- List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_good);
- when(_serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
- List<RangerEnumDef> enumDefs = _utils.createEnumDefs(enums_good);
- when(_serviceDef.getEnums()).thenReturn(enumDefs);
-
- // create: id is not relevant, name should not conflict
- when(_serviceDef.getId()).thenReturn(null); // id is not relevant for create
- when(_serviceDef.getName()).thenReturn("aServiceDef"); // service has a name
- when(_store.getServiceDefByName("aServiceDef")).thenReturn(null); // no name collision
- assertTrue(_validator.isValid(_serviceDef, Action.CREATE, _failures));
- assertTrue(_failures.isEmpty());
-
- // update: id should match existing service, name should not point to different service def
- when(_serviceDef.getId()).thenReturn(5L);
- RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
- when(_store.getServiceDef(5L)).thenReturn(existingServiceDef);
- assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
- assertTrue(_failures.isEmpty());
-
- // update: if name points to a service that it's id should be the same
- RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
- when(anotherExistingServiceDef.getId()).thenReturn(5L);
- when(_store.getServiceDefByName("aServiceDef")).thenReturn(anotherExistingServiceDef);
- assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
- assertTrue(_failures.isEmpty());
- }
-
- @Test
- public final void testIsValid_Long_failures() throws Exception {
- Long id = null;
- // passing in wrong action type
- boolean result = _validator.isValid((Long)null, Action.CREATE, _failures);
- assertFalse(result);
- _utils.checkFailureForInternalError(_failures);
- // passing in null id is an error
- _failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
- _utils.checkFailureForMissingValue(_failures, "id");
- // a service def with that id should exist, else it is an error
- id = 3L;
- when(_store.getServiceDef(id)).thenReturn(null);
- _failures.clear(); assertFalse(_validator.isValid(id, Action.DELETE, _failures));
- _utils.checkFailureForSemanticError(_failures, "id");
- // happypath
- when(_store.getServiceDef(id)).thenReturn(_serviceDef);
- _failures.clear(); assertTrue(_validator.isValid(id, Action.DELETE, _failures));
- assertTrue(_failures.isEmpty());
- }
-
- @Test
- public final void testIsValid_failures_name() throws Exception {
- // null service def and bad service def name
- for (Action action : cu) {
- // passing in null service def is an error
- assertFalse(_validator.isValid((RangerServiceDef)null, action, _failures));
- _utils.checkFailureForMissingValue(_failures, "service def");
- // name should be valid
- for (String name : new String[] { null, "", " " }) {
- when(_serviceDef.getName()).thenReturn(name);
- _failures.clear(); assertFalse(_validator.isValid(_serviceDef, action, _failures));
- _utils.checkFailureForMissingValue(_failures, "name");
- }
- }
- }
-
- @Test
- public final void testIsValid_failures_id() throws Exception {
- // id is required for update
- when(_serviceDef.getId()).thenReturn(null);
- assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
- _utils.checkFailureForMissingValue(_failures, "id");
-
- // update: service should exist for the passed in id
- Long id = 7L;
- when(_serviceDef.getId()).thenReturn(id);
- when(_store.getServiceDef(id)).thenReturn(null);
- assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
- _utils.checkFailureForSemanticError(_failures, "id");
-
- when(_store.getServiceDef(id)).thenThrow(new Exception());
- assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
- _utils.checkFailureForSemanticError(_failures, "id");
- }
-
- @Test
- public final void testIsValid_failures_nameId_create() throws Exception {
- // service shouldn't exist with the name
- RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
- when(_store.getServiceDefByName("existing-service")).thenReturn(existingServiceDef);
- when(_serviceDef.getName()).thenReturn("existing-service");
- _failures.clear(); assertFalse(_validator.isValid(_serviceDef, Action.CREATE, _failures));
- _utils.checkFailureForSemanticError(_failures, "name");
- }
-
- @Test
- public final void testIsValid_failures_nameId_update() throws Exception {
-
- // update: if service exists with the same name then it can't point to a different service
- Long id = 7L;
- when(_serviceDef.getId()).thenReturn(id);
- RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
- when(existingServiceDef.getId()).thenReturn(id);
- when(_store.getServiceDef(id)).thenReturn(existingServiceDef);
-
- String name = "aServiceDef";
- when(_serviceDef.getName()).thenReturn(name);
- RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
- Long anotherId = 49L;
- when(anotherExistingServiceDef.getId()).thenReturn(anotherId);
- when(_store.getServiceDefByName(name)).thenReturn(anotherExistingServiceDef);
-
- assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
- _utils.checkFailureForSemanticError(_failures, "id/name");
- }
-
- final Object[][] accessTypes_bad_unknownType = new Object[][] {
- { "read", null }, // ok, null implied grants
- { "write", new String[] { } }, // ok, empty implied grants
- { "admin", new String[] { "ReaD", "execute" } } // non-existent access type (execute), read is good (case should not matter)
- };
-
- final Object[][] accessTypes_bad_selfReference = new Object[][] {
- { "read", null }, // ok, null implied grants
- { "write", new String[] { } }, // ok, empty implied grants
- { "admin", new String[] { "write", "admin" } } // non-existent access type (execute)
- };
-
- @Test
- public final void test_isValidAccessTypes_happyPath() {
- List<RangerAccessTypeDef> input = _utils.createAccessTypeDefs(accessTypes_good);
- assertTrue(_validator.isValidAccessTypes(input, _failures));
- assertTrue(_failures.isEmpty());
- }
-
- @Test
- public final void test_isValidAccessTypes_failures() {
- // sending in empty null access type defs is ok
- assertTrue(_validator.isValidAccessTypes(null, _failures));
- assertTrue(_failures.isEmpty());
-
- List<RangerAccessTypeDef> input = new ArrayList<RangerAccessTypeDef>();
- _failures.clear(); assertTrue(_validator.isValidAccessTypes(input, _failures));
- assertTrue(_failures.isEmpty());
-
- // null/empty access types
- List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(new String[] { null, "", " " });
- _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
- _utils.checkFailureForMissingValue(_failures, "access type name");
-
- // duplicate access types
- accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "read" } );
- _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
- _utils.checkFailureForSemanticError(_failures, "access type name", "read");
-
- // duplicate access types - case-insensitive
- accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "READ" } );
- _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
- _utils.checkFailureForSemanticError(_failures, "access type name", "READ");
-
- // unknown access type in implied grants list
- accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_unknownType);
- _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
- _utils.checkFailureForSemanticError(_failures, "implied grants", "execute");
-
- // access type with implied grant referring to itself
- accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_selfReference);
- _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
- _utils.checkFailureForSemanticError(_failures, "implied grants", "admin");
- }
-
- final Map<String, String[]> enums_bad_enumName_null = ImmutableMap.of(
- "authentication-type", new String[] { "simple", "kerberos" },
- "time-unit", new String[] { "day", "hour", "minute" },
- "null", new String[] { "foo", "bar", "tar" } // null enum-name -- "null" is a special value that leads to a null enum name
- );
-
- final Map<String, String[]> enums_bad_enumName_blank = ImmutableMap.of(
- "authentication-type", new String[] { "simple", "kerberos" },
- "time-unit", new String[] { "day", "hour", "minute" },
- " ", new String[] { "foo", "bar", "tar" } // enum name is all spaces
- );
-
- final Map<String, String[]> enums_bad_Elements_empty = ImmutableMap.of(
- "authentication-type", new String[] { "simple", "kerberos" },
- "time-unit", new String[] { "day", "hour", "minute" },
- "anEnum", new String[] { } // enum elements collection is empty
- );
-
- final Map<String, String[]> enums_bad_enumName_duplicate_exact = ImmutableMap.of(
- "authentication-type", new String[] { "simple", "kerberos" },
- "time-unit", new String[] { "day", "hour", "minute" }
- );
-
- final Map<String, String[]> enums_bad_enumName_duplicate_differentCase = ImmutableMap.of(
- "authentication-type", new String[] { "simple", "kerberos" },
- "time-unit", new String[] { "day", "hour", "minute" },
- "Authentication-Type", new String[] { } // duplicate enum-name different in case
- );
-
- @Test
- public final void test_isValidEnums_happyPath() {
- List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
- assertTrue(_validator.isValidEnums(input, _failures));
- assertTrue(_failures.isEmpty());
- }
-
- @Test
- public final void test_isValidEnums_failures() {
- // null elements in enum def list are a failure
- List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
- input.add(null);
- assertFalse(_validator.isValidEnums(input, _failures));
- _utils.checkFailureForMissingValue(_failures, "enum def");
-
- // enum names should be valid
- input = _utils.createEnumDefs(enums_bad_enumName_null);
- _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
- _utils.checkFailureForMissingValue(_failures, "enum def name");
-
- input = _utils.createEnumDefs(enums_bad_enumName_blank);
- _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
- _utils.checkFailureForMissingValue(_failures, "enum def name");
-
- // enum elements collection should not be null or empty
- input = _utils.createEnumDefs(enums_good);
- RangerEnumDef anEnumDef = mock(RangerEnumDef.class);
- when(anEnumDef.getName()).thenReturn("anEnum");
- when(anEnumDef.getElements()).thenReturn(null);
- input.add(anEnumDef);
- _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
- _utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
-
- input = _utils.createEnumDefs(enums_bad_Elements_empty);
- _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
- _utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
-
- // enum names should be distinct -- exact match
- input = _utils.createEnumDefs(enums_good);
- // add an element with same name as the first element
- String name = input.iterator().next().getName();
- when(anEnumDef.getName()).thenReturn(name);
- List<RangerEnumElementDef> elementDefs = _utils.createEnumElementDefs(new String[] {"val1", "val2"});
- when(anEnumDef.getElements()).thenReturn(elementDefs);
- input.add(anEnumDef);
- _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
- _utils.checkFailureForSemanticError(_failures, "enum def name", name);
-
- // enum names should be distinct -- case insensitive
- input = _utils.createEnumDefs(enums_bad_enumName_duplicate_differentCase);
- _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
- _utils.checkFailureForSemanticError(_failures, "enum def name", "Authentication-Type");
-
- // enum default index should be right
- input = _utils.createEnumDefs(enums_good);
- // set the index of 1st on to be less than 0
- when(input.iterator().next().getDefaultIndex()).thenReturn(-1);
- _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
- _utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
- // set the index to be more than number of elements
- when(input.iterator().next().getDefaultIndex()).thenReturn(2);
- _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
- _utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
- }
-
- @Test
- public final void test_isValidEnumElements_happyPath() {
- List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
- assertTrue(_validator.isValidEnumElements(input, _failures, "anEnum"));
- assertTrue(_failures.isEmpty());
- }
-
- @Test
- public final void test_isValidEnumElements_failures() {
- // enum element collection should not have nulls in it
- List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
- input.add(null);
- assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
- _utils.checkFailureForMissingValue(_failures, "enum element", "anEnum");
-
- // element names can't be null/empty
- input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", null });
- _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
- _utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
-
- input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", " " }); // two tabs
- _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
- _utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
-
- // element names should be distinct - case insensitive
- input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kerberos" }); // duplicate name - exact match
- _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
- _utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
-
- input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kErbErOs" }); // duplicate name - different case
- _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
- _utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
- }
-
- private ValidationTestUtils _utils = new ValidationTestUtils();
- RangerServiceDef _serviceDef;
- List<ValidationFailureDetails> _failures;
- ServiceStore _store;
- RangerServiceDefValidator _validator;
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java
deleted file mode 100644
index 6465cca..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * 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.rest;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.rest.RangerServiceValidator;
-import org.apache.ranger.rest.ValidationFailureDetails;
-import org.apache.ranger.rest.RangerValidator.Action;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestRangerServiceValidator {
-
- final Action[] cud = new Action[] { Action.CREATE, Action.UPDATE, Action.DELETE };
- final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
- final Action[] ud = new Action[] { Action.UPDATE, Action.DELETE };
-
- @Before
- public void before() {
- _store = mock(ServiceStore.class);
- _action = Action.CREATE; // by default we set action to create
- _validator = new RangerServiceValidator(_store);
- }
-
- void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field) {
- checkFailure_isValid(validator, service, action, failures, errorType, field, null);
- }
-
- void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field, String subField) {
- failures.clear();
- assertFalse(validator.isValid(service, action, failures));
- switch (errorType) {
- case "missing":
- _utils.checkFailureForMissingValue(failures, field, subField);
- break;
- case "semantic":
- _utils.checkFailureForSemanticError(failures, field, subField);
- break;
- case "internal error":
- _utils.checkFailureForInternalError(failures);
- break;
- default:
- fail("Unsupported errorType[" + errorType + "]");
- break;
- }
- }
-
- @Test
- public void testIsValid_failures() throws Exception {
- RangerService service = mock(RangerService.class);
- // passing in a null service to the check itself is an error
- assertFalse(_validator.isValid((RangerService)null, _action, _failures));
- _utils.checkFailureForMissingValue(_failures, "service");
-
- // id is required for update
- when(service.getId()).thenReturn(null);
- // let's verify the failure and the sort of error information that is returned (for one of these)
- // assert that among the failure reason is one about id being missing.
- checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "missing", "id");
- when(service.getId()).thenReturn(7L);
-
- for (Action action : cu) {
- // null, empty of blank name renders a service invalid
- for (String name : new String[] { null, "", " " }) { // spaces and tabs
- when(service.getName()).thenReturn(name);
- checkFailure_isValid(_validator, service, action, _failures, "missing", "name");
- }
- // same is true for the type
- for (String type : new String[] { null, "", " " }) {
- when(service.getType()).thenReturn(type);
- checkFailure_isValid(_validator, service, action, _failures, "missing", "type");
- }
- }
- when(service.getName()).thenReturn("aName");
-
- // if non-empty, then the type should exist!
- when(_store.getServiceDefByName("null-type")).thenReturn(null);
- when(_store.getServiceDefByName("throwing-type")).thenThrow(new Exception());
- for (Action action : cu) {
- for (String type : new String[] { "null-type", "throwing-type" }) {
- when(service.getType()).thenReturn(type);
- checkFailure_isValid(_validator, service, action, _failures, "semantic", "type");
- }
- }
- when(service.getType()).thenReturn("aType");
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
-
- // Create: No service should exist matching its id and/or name
- RangerService anExistingService = mock(RangerService.class);
- when(_store.getServiceByName("aName")).thenReturn(anExistingService);
- checkFailure_isValid(_validator, service, Action.CREATE, _failures, "semantic", "name");
-
- // Update: service should exist matching its id and name specified should not belong to a different service
- when(_store.getService(7L)).thenReturn(null);
- when(_store.getServiceByName("aName")).thenReturn(anExistingService);
- checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "semantic", "id");
-
- when(_store.getService(7L)).thenReturn(anExistingService);
- RangerService anotherExistingService = mock(RangerService.class);
- when(anotherExistingService.getId()).thenReturn(49L);
- when(_store.getServiceByName("aName")).thenReturn(anotherExistingService);
- checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "semantic", "id/name");
- }
-
- @Test
- public void test_isValid_missingRequiredParameter() throws Exception {
- // Create/Update: simulate a condition where required parameters are missing
- Object[][] input = new Object[][] {
- { "param1", true },
- { "param2", true },
- { "param3", false },
- { "param4", false },
- };
- List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(input);
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- when(serviceDef.getConfigs()).thenReturn(configDefs);
- // wire this service def into store
- when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
- // create a service with some require parameters missing
- RangerService service = mock(RangerService.class);
- when(service.getType()).thenReturn("aType");
- when(service.getName()).thenReturn("aName");
- // required parameters param2 is missing
- String[] params = new String[] { "param1", "param3", "param4", "param5" };
- Map<String, String> paramMap = _utils.createMap(params);
- when(service.getConfigs()).thenReturn(paramMap);
- // service does not exist in the store
- when(_store.getServiceByName("aService")).thenReturn(null);
- for (Action action : cu) {
- // it should be invalid
- checkFailure_isValid(_validator, service, action, _failures, "missing", "configuration", "param2");
- }
- }
-
- @Test
- public void test_isValid_happyPath() throws Exception {
- // create a service def with some required parameters
- Object[][] serviceDefInput = new Object[][] {
- { "param1", true },
- { "param2", true },
- { "param3", false },
- { "param4", false },
- { "param5", true },
- };
- List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(serviceDefInput);
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- when(serviceDef.getConfigs()).thenReturn(configDefs);
- // create a service with some parameters on it
- RangerService service = mock(RangerService.class);
- when(service.getName()).thenReturn("aName");
- when(service.getType()).thenReturn("aType");
- // contains an extra parameter (param6) and one optional is missing(param4)
- String[] configs = new String[] { "param1", "param2", "param3", "param5", "param6" };
- Map<String, String> configMap = _utils.createMap(configs);
- when(service.getConfigs()).thenReturn(configMap);
- // wire then into the store
- // service does not exists
- when(_store.getServiceByName("aName")).thenReturn(null);
- // service def exists
- when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
-
- assertTrue(_validator.isValid(service, Action.CREATE, _failures));
-
- // for update to work the only additional requirement is that id is required and service should exist
- // if name is not null and it points to a service then it should match the id
- when(service.getId()).thenReturn(7L);
- RangerService existingService = mock(RangerService.class);
- when(existingService.getId()).thenReturn(7L);
- when(_store.getService(7L)).thenReturn(existingService);
- when(_store.getServiceByName("aName")).thenReturn(existingService);
- assertTrue(_validator.isValid(service, Action.UPDATE, _failures));
- // name need not point to a service for update to work, of course.
- when(_store.getServiceByName("aName")).thenReturn(null);
- assertTrue(_validator.isValid(service, Action.UPDATE, _failures));
- }
-
- @Test
- public void test_isValid_withId_errorConditions() throws Exception {
- // api that takes in long is only supported for delete currently
- assertFalse(_validator.isValid(1L, Action.CREATE, _failures));
- _utils.checkFailureForInternalError(_failures);
- // passing in a null id is a failure!
- _validator = new RangerServiceValidator(_store);
- _failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
- _utils.checkFailureForMissingValue(_failures, "id");
- // if service with that id does not exist then that, too, is a failure
- when(_store.getService(1L)).thenReturn(null);
- when(_store.getService(2L)).thenThrow(new Exception());
- _failures.clear(); assertFalse(_validator.isValid(1L, Action.DELETE, _failures));
- _utils.checkFailureForSemanticError(_failures, "id");
-
- _failures.clear(); assertFalse(_validator.isValid(2L, Action.DELETE, _failures));
- _utils.checkFailureForSemanticError(_failures, "id");
- }
-
- @Test
- public void test_isValid_withId_happyPath() throws Exception {
- _validator = new RangerServiceValidator(_store);
- RangerService service = mock(RangerService.class);
- when(_store.getService(1L)).thenReturn(service);
- assertTrue(_validator.isValid(1L, Action.DELETE, _failures));
- }
-
- private ServiceStore _store;
- private RangerServiceValidator _validator;
- private Action _action;
- private ValidationTestUtils _utils = new ValidationTestUtils();
- private List<ValidationFailureDetails> _failures = new ArrayList<ValidationFailureDetails>();
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
deleted file mode 100644
index cbaaf60..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * 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.rest;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.ranger.plugin.model.RangerPolicy;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.plugin.util.SearchFilter;
-import org.apache.ranger.rest.RangerValidator;
-import org.apache.ranger.rest.RangerValidator.Action;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.collect.Maps;
-
-public class TestRangerValidator {
-
- static class RangerValidatorForTest extends RangerValidator {
-
- public RangerValidatorForTest(ServiceStore store) {
- super(store);
- }
-
- boolean isValid(String behavior) {
- boolean valid;
- if (behavior.equals("valid")) {
- valid = true;
- } else {
- valid = false;
- }
- return valid;
- }
- }
-
- @Before
- public void before() {
- _store = mock(ServiceStore.class);
- _validator = new RangerValidatorForTest(_store);
- }
-
- @Test
- public void test_ctor_firewalling() {
- try {
- // service store can't be null during construction
- new RangerValidatorForTest(null);
- fail("Should have thrown exception!");
- } catch (IllegalArgumentException e) {
- // expected exception
- }
- }
-
- @Test
- public void test_validate() {
- // default implementation should fail. This is abstract class. Sub-class must do something sensible with isValid
- try {
- _validator.validate(1L, Action.CREATE);
- fail("Should have thrown exception!");
- } catch (Exception e) {
- // ok expected exception
- String message = e.getMessage();
- assertTrue(message.contains("internal error"));
- }
- }
-
- @Test
- public void test_getServiceConfigParameters() {
- // reasonable protection against null values
- Set<String> parameters = _validator.getServiceConfigParameters(null);
- assertNotNull(parameters);
- assertTrue(parameters.isEmpty());
-
- RangerService service = mock(RangerService.class);
- when(service.getConfigs()).thenReturn(null);
- parameters = _validator.getServiceConfigParameters(service);
- assertNotNull(parameters);
- assertTrue(parameters.isEmpty());
-
- when(service.getConfigs()).thenReturn(new HashMap<String, String>());
- parameters = _validator.getServiceConfigParameters(service);
- assertNotNull(parameters);
- assertTrue(parameters.isEmpty());
-
- String[] keys = new String[] { "a", "b", "c" };
- Map<String, String> map = _utils.createMap(keys);
- when(service.getConfigs()).thenReturn(map);
- parameters = _validator.getServiceConfigParameters(service);
- for (String key: keys) {
- assertTrue("key", parameters.contains(key));
- }
- }
-
- @Test
- public void test_getRequiredParameters() {
- // reasonable protection against null things
- Set<String> parameters = _validator.getRequiredParameters(null);
- assertNotNull(parameters);
- assertTrue(parameters.isEmpty());
-
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- when(serviceDef.getConfigs()).thenReturn(null);
- parameters = _validator.getRequiredParameters(null);
- assertNotNull(parameters);
- assertTrue(parameters.isEmpty());
-
- List<RangerServiceConfigDef> configs = new ArrayList<RangerServiceDef.RangerServiceConfigDef>();
- when(serviceDef.getConfigs()).thenReturn(configs);
- parameters = _validator.getRequiredParameters(null);
- assertNotNull(parameters);
- assertTrue(parameters.isEmpty());
-
- Object[][] input = new Object[][] {
- { "param1", false },
- { "param2", true },
- { "param3", true },
- { "param4", false },
- };
- configs = _utils.createServiceConditionDefs(input);
- when(serviceDef.getConfigs()).thenReturn(configs);
- parameters = _validator.getRequiredParameters(serviceDef);
- assertTrue("result does not contain: param2", parameters.contains("param2"));
- assertTrue("result does not contain: param3", parameters.contains("param3"));
- }
-
- @Test
- public void test_getServiceDef() {
- try {
- // if service store returns null or throws an exception then service is deemed invalid
- when(_store.getServiceDefByName("return null")).thenReturn(null);
- when(_store.getServiceDefByName("throw")).thenThrow(new Exception());
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- when(_store.getServiceDefByName("good-service")).thenReturn(serviceDef);
- } catch (Exception e) {
- e.printStackTrace();
- fail("Unexpected exception during mocking!");
- }
-
- assertNull(_validator.getServiceDef("return null"));
- assertNull(_validator.getServiceDef("throw"));
- assertFalse(_validator.getServiceDef("good-service") == null);
- }
-
- @Test
- public void test_getPolicy() throws Exception {
- // if service store returns null or throws an exception then return null policy
- when(_store.getPolicy(1L)).thenReturn(null);
- when(_store.getPolicy(2L)).thenThrow(new Exception());
- RangerPolicy policy = mock(RangerPolicy.class);
- when(_store.getPolicy(3L)).thenReturn(policy);
-
- assertNull(_validator.getPolicy(1L));
- assertNull(_validator.getPolicy(2L));
- assertTrue(_validator.getPolicy(3L) != null);
- }
-
- @Test
- public void test_getService_byId() throws Exception {
- // if service store returns null or throws an exception then service is deemed invalid
- when(_store.getService(1L)).thenReturn(null);
- when(_store.getService(2L)).thenThrow(new Exception());
- RangerService service = mock(RangerService.class);
- when(_store.getService(3L)).thenReturn(service);
-
- assertNull(_validator.getService(1L));
- assertNull(_validator.getService(2L));
- assertTrue(_validator.getService(3L) != null);
- }
-
- @Test
- public void test_getService() {
- try {
- // if service store returns null or throws an exception then service is deemed invalid
- when(_store.getServiceByName("return null")).thenReturn(null);
- when(_store.getServiceByName("throw")).thenThrow(new Exception());
- RangerService service = mock(RangerService.class);
- when(_store.getServiceByName("good-service")).thenReturn(service);
- } catch (Exception e) {
- e.printStackTrace();
- fail("Unexpected exception during mocking!");
- }
-
- assertNull(_validator.getService("return null"));
- assertNull(_validator.getService("throw"));
- assertFalse(_validator.getService("good-service") == null);
- }
-
- @Test
- public void test_getAccessTypes() {
- // passing in null service def
- Set<String> accessTypes = _validator.getAccessTypes((RangerServiceDef)null);
- assertTrue(accessTypes.isEmpty());
- // that has null or empty access type def
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- when(serviceDef.getAccessTypes()).thenReturn(null);
- accessTypes = _validator.getAccessTypes(serviceDef);
- assertTrue(accessTypes.isEmpty());
-
- List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
- when(serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
- accessTypes = _validator.getAccessTypes(serviceDef);
- assertTrue(accessTypes.isEmpty());
-
- // having null accesstypedefs
- accessTypeDefs.add(null);
- accessTypes = _validator.getAccessTypes(serviceDef);
- assertTrue(accessTypes.isEmpty());
-
- // access type defs with null empty blank names are skipped, spaces within names are preserved
- String[] names = new String[] { null, "", "a", " ", "b ", " ", " C", " D " };
- accessTypeDefs.addAll(_utils.createAccessTypeDefs(names));
- accessTypes = _validator.getAccessTypes(serviceDef);
- assertEquals(4, accessTypes.size());
- assertTrue(accessTypes.contains("a"));
- assertTrue(accessTypes.contains("b "));
- assertTrue(accessTypes.contains(" c"));
- assertTrue(accessTypes.contains(" d "));
- }
-
- @Test
- public void test_getResourceNames() {
- // passing in null service def
- Set<String> accessTypes = _validator.getMandatoryResourceNames((RangerServiceDef)null);
- assertTrue(accessTypes.isEmpty());
- // that has null or empty access type def
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- when(serviceDef.getResources()).thenReturn(null);
- accessTypes = _validator.getMandatoryResourceNames(serviceDef);
- assertTrue(accessTypes.isEmpty());
-
- List<RangerResourceDef> resourceDefs = new ArrayList<RangerResourceDef>();
- when(serviceDef.getResources()).thenReturn(resourceDefs);
- accessTypes = _validator.getMandatoryResourceNames(serviceDef);
- assertTrue(accessTypes.isEmpty());
-
- // having null accesstypedefs
- resourceDefs.add(null);
- accessTypes = _validator.getMandatoryResourceNames(serviceDef);
- assertTrue(accessTypes.isEmpty());
-
- // access type defs with null empty blank names are skipped, spaces within names are preserved
- Object[][] data = {
- { "a", true }, // all good
- null, // this should put a null element in the resource def!
- { "b", null }, // mandatory field is null, i.e. false
- { "c", false }, // non-mandatory field false - upper case
- { "D", true }, // resource specified in upper case
- { "E", false }, // all good
- };
- resourceDefs.addAll(_utils.createResourceDefs(data));
- accessTypes = _validator.getMandatoryResourceNames(serviceDef);
- assertEquals(2, accessTypes.size());
- assertTrue(accessTypes.contains("a"));
- assertTrue(accessTypes.contains("d")); // name should come back lower case
-
- accessTypes = _validator.getAllResourceNames(serviceDef);
- assertEquals(5, accessTypes.size());
- assertTrue(accessTypes.contains("b"));
- assertTrue(accessTypes.contains("c"));
- assertTrue(accessTypes.contains("e"));
- }
-
- @Test
- public void test_getValidationRegExes() {
- // passing in null service def
- Map<String, String> regExMap = _validator.getValidationRegExes((RangerServiceDef)null);
- assertTrue(regExMap.isEmpty());
- // that has null or empty access type def
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- when(serviceDef.getResources()).thenReturn(null);
- regExMap = _validator.getValidationRegExes(serviceDef);
- assertTrue(regExMap.isEmpty());
-
- List<RangerResourceDef> resourceDefs = new ArrayList<RangerResourceDef>();
- when(serviceDef.getResources()).thenReturn(resourceDefs);
- regExMap = _validator.getValidationRegExes(serviceDef);
- assertTrue(regExMap.isEmpty());
-
- // having null accesstypedefs
- resourceDefs.add(null);
- regExMap = _validator.getValidationRegExes(serviceDef);
- assertTrue(regExMap.isEmpty());
-
- // access type defs with null empty blank names are skipped, spaces within names are preserved
- String[][] data = {
- { "a", null }, // null-regex
- null, // this should put a null element in the resource def!
- { "b", "regex1" }, // valid
- { "c", "" }, // empty regex
- { "d", "regex2" }, // valid
- { "e", " " }, // blank regex
- { "f", "regex3" }, // all good
- };
- resourceDefs.addAll(_utils.createResourceDefsWithRegEx(data));
- regExMap = _validator.getValidationRegExes(serviceDef);
- assertEquals(3, regExMap.size());
- assertEquals("regex1", regExMap.get("b"));
- assertEquals("regex2", regExMap.get("d"));
- assertEquals("regex3", regExMap.get("f"));
- }
-
- @Test
- public void test_getPolicyResources() {
-
- Set<String> result;
- RangerPolicy policy = null;
- // null policy
- result = _validator.getPolicyResources(null);
- assertTrue(result != null);
- assertTrue(result.isEmpty());
- // null resource map
- policy = mock(RangerPolicy.class);
- when(policy.getResources()).thenReturn(null);
- result = _validator.getPolicyResources(null);
- assertTrue(result != null);
- assertTrue(result.isEmpty());
- // empty resource map
- Map<String, RangerPolicyResource> input = Maps.newHashMap();
- when(policy.getResources()).thenReturn(input);
- result = _validator.getPolicyResources(policy);
- assertTrue(result != null);
- assertTrue(result.isEmpty());
- // known resource map
- input.put("r1", mock(RangerPolicyResource.class));
- input.put("R2", mock(RangerPolicyResource.class));
- result = _validator.getPolicyResources(policy);
- assertEquals(2, result.size());
- assertTrue("r1", result.contains("r1"));
- assertTrue("R2", result.contains("r2")); // result should lowercase the resource-names
- }
-
- @Test
- public void test_getIsAuditEnabled() {
- // null policy
- RangerPolicy policy = null;
- boolean result = _validator.getIsAuditEnabled(policy);
- assertFalse(result);
- // null isAuditEnabled Boolean is supposed to be TRUE!!
- policy = mock(RangerPolicy.class);
- when(policy.getIsAuditEnabled()).thenReturn(null);
- result = _validator.getIsAuditEnabled(policy);
- assertTrue(result);
- // non-null value
- when(policy.getIsAuditEnabled()).thenReturn(Boolean.FALSE);
- result = _validator.getIsAuditEnabled(policy);
- assertFalse(result);
-
- when(policy.getIsAuditEnabled()).thenReturn(Boolean.TRUE);
- result = _validator.getIsAuditEnabled(policy);
- assertTrue(result);
- }
-
- @Test
- public void test_getPolicies() throws Exception {
-
- // returns null when store returns null
- String policyName = "aPolicy";
- String serviceName = "aService";
- SearchFilter filter = new SearchFilter();
- filter.setParam(SearchFilter.POLICY_NAME, policyName);
- filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
-
- when(_store.getPolicies(filter)).thenReturn(null);
- List<RangerPolicy> result = _validator.getPolicies(policyName, serviceName);
- // validate store is queried with both parameters
- verify(_store).getPolicies(filter);
- assertNull(result);
-
- // returns null if store throws an exception
- when(_store.getPolicies(filter)).thenThrow(new Exception());
- result = _validator.getPolicies(policyName, serviceName);
- assertNull(result);
- }
-
- @Test
- public void test_getServiceDef_byId() throws Exception {
- // if service store returns null or throws an exception then service is deemed invalid
- when(_store.getServiceDef(1L)).thenReturn(null);
- when(_store.getServiceDef(2L)).thenThrow(new Exception());
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- when(_store.getServiceDef(3L)).thenReturn(serviceDef);
-
- assertNull(_validator.getServiceDef(1L));
- assertNull(_validator.getServiceDef(2L));
- assertTrue(_validator.getServiceDef(3L) != null);
- }
-
- @Test
- public void test_getEnumDefaultIndex() {
- RangerEnumDef enumDef = mock(RangerEnumDef.class);
- assertEquals(-1, _validator.getEnumDefaultIndex(null));
- when(enumDef.getDefaultIndex()).thenReturn(null);
- assertEquals(0, _validator.getEnumDefaultIndex(enumDef));
- when(enumDef.getDefaultIndex()).thenReturn(-5);
- assertEquals(-5, _validator.getEnumDefaultIndex(enumDef));
- }
-
- @Test
- public void test_getImpliedGrants() {
-
- // passing in null gets back a null
- Collection<String> result = _validator.getImpliedGrants(null);
- assertNull(result);
-
- // null or empty implied grant collection gets back an empty collection
- RangerAccessTypeDef accessTypeDef = mock(RangerAccessTypeDef.class);
- when(accessTypeDef.getImpliedGrants()).thenReturn(null);
- result = _validator.getImpliedGrants(accessTypeDef);
- assertTrue(result.isEmpty());
-
- List<String> impliedGrants = new ArrayList<String>();
- when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
- result = _validator.getImpliedGrants(accessTypeDef);
- assertTrue(result.isEmpty());
-
- // null/empty values come back as is
- impliedGrants = Arrays.asList(new String[] { null, "", " ", " " });
- when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
- result = _validator.getImpliedGrants(accessTypeDef);
- assertEquals(4, result.size());
-
- // non-empty values get lower cased
- impliedGrants = Arrays.asList(new String[] { "a", "B", "C ", " d " });
- when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
- result = _validator.getImpliedGrants(accessTypeDef);
- assertEquals(4, result.size());
- assertTrue(result.contains("a"));
- assertTrue(result.contains("b"));
- assertTrue(result.contains("c "));
- assertTrue(result.contains(" d "));
- }
-
- private RangerValidatorForTest _validator;
- private ServiceStore _store;
- private ValidationTestUtils _utils = new ValidationTestUtils();
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
index 5a2ba80..b33cd97 100644
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
+++ b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
@@ -38,8 +38,12 @@ import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.validation.RangerPolicyValidator;
+import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.RangerServiceValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidatorFactory;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
import org.apache.ranger.rest.ServiceREST;
-import org.apache.ranger.rest.RangerValidator.Action;
import org.junit.Before;
import org.junit.Test;
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java b/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
deleted file mode 100644
index 3c1c463..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * 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.rest;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.rest.ValidationFailureDetails;
-
-public class ValidationTestUtils {
-
- Map<String, String> createMap(String[] keys) {
- Map<String, String> result = new HashMap<String, String>();
- for (String key : keys) {
- result.put(key, "valueof-" + key);
- }
- return result;
- }
-
- // helper methods for tests
- List<RangerServiceConfigDef> createServiceConditionDefs(Object[][] input) {
- List<RangerServiceConfigDef> result = new ArrayList<RangerServiceDef.RangerServiceConfigDef>();
-
- for (Object data[] : input) {
- RangerServiceConfigDef aConfigDef = mock(RangerServiceConfigDef.class);
- when(aConfigDef.getName()).thenReturn((String)data[0]);
- when(aConfigDef.getMandatory()).thenReturn((boolean)data[1]);
- result.add(aConfigDef);
- }
-
- return result;
- }
-
- void checkFailureForSemanticError(List<ValidationFailureDetails> failures, String fieldName) {
- checkFailure(failures, null, null, true, fieldName, null);
- }
-
- void checkFailureForSemanticError(List<ValidationFailureDetails> failures, String fieldName, String subField) {
- checkFailure(failures, null, null, true, fieldName, subField);
- }
-
- void checkFailureForMissingValue(List<ValidationFailureDetails> failures, String field) {
- checkFailure(failures, null, true, null, field, null);
- }
-
- void checkFailureForMissingValue(List<ValidationFailureDetails> failures, String field, String subField) {
- checkFailure(failures, null, true, null, field, subField);
- }
-
- void checkFailureForInternalError(List<ValidationFailureDetails> failures, String fieldName) {
- checkFailure(failures, true, null, null, fieldName, null);
- }
-
- void checkFailureForInternalError(List<ValidationFailureDetails> failures) {
- checkFailure(failures, true, null, null, null, null);
- }
-
- void checkFailure(List<ValidationFailureDetails> failures, Boolean internalError, Boolean missing, Boolean semanticError, String field, String subField) {
- if (CollectionUtils.isEmpty(failures)) {
- fail("List of failures is null/empty!");
- } else {
- boolean found = false;
- for (ValidationFailureDetails f : failures) {
- if ((internalError == null || internalError == f._internalError) &&
- (missing == null || missing == f._missing) &&
- (semanticError == null || semanticError == f._semanticError) &&
- (field == null || field.equals(f._fieldName)) &&
- (subField == null || subField.equals(f._subFieldName))) {
- found = true;
- }
- }
- assertTrue(found);
- }
- }
-
- List<RangerAccessTypeDef> createAccessTypeDefs(String[] names) {
- assertFalse(names == null); // fail if null is passed in!
- List<RangerAccessTypeDef> defs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
- for (String name : names) {
- RangerAccessTypeDef def = mock(RangerAccessTypeDef.class);
- when(def.getName()).thenReturn(name);
- defs.add(def);
- }
- return defs;
- }
-
-
- List<RangerAccessTypeDef> createAccessTypeDefs(Object[][] data) {
- if (data == null) {
- return null;
- }
- List<RangerAccessTypeDef> result = new ArrayList<RangerAccessTypeDef>();
- if (data.length == 0) {
- return result;
- }
- for (Object[] entry : data) {
- String accessType = (String)entry[0];
- String[] impliedAccessArray = (String[])entry[1];
- List<String> impliedAccesses = null;
- if (impliedAccessArray != null) {
- impliedAccesses = Arrays.asList(impliedAccessArray);
- }
- RangerAccessTypeDef aTypeDef = mock(RangerAccessTypeDef.class);
- when(aTypeDef.getName()).thenReturn(accessType);
- when(aTypeDef.getImpliedGrants()).thenReturn(impliedAccesses);
- result.add(aTypeDef);
- }
- return result;
- }
-
- RangerServiceDef createServiceDefWithAccessTypes(String[] accesses) {
- RangerServiceDef serviceDef = mock(RangerServiceDef.class);
- List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
- for (String access : accesses) {
- RangerAccessTypeDef accessTypeDef = mock(RangerAccessTypeDef.class);
- when(accessTypeDef.getName()).thenReturn(access);
- accessTypeDefs.add(accessTypeDef);
- }
- when(serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
- return serviceDef;
- }
-
- List<RangerPolicyItemAccess> createItemAccess(Object[][] data) {
- List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicyItemAccess>();
- for (Object[] row : data) {
- RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
- when(access.getType()).thenReturn((String)row[0]);
- when(access.getIsAllowed()).thenReturn((Boolean)row[1]);
- accesses.add(access);
- }
- return accesses;
- }
-
- List<RangerPolicyItem> createPolicyItems(Object[] data) {
- List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicyItem>();
- for (Object object : data) {
- @SuppressWarnings("unchecked")
- Map<String, Object[]> map = (Map<String, Object[]>) object;
- RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
-
- List<String> usersList = null;
- if (map.containsKey("users")) {
- usersList = Arrays.asList((String[])map.get("users"));
- }
- when(policyItem.getUsers()).thenReturn(usersList);
-
- List<String> groupsList = null;
- if (map.containsKey("groups")) {
- groupsList = Arrays.asList((String[])map.get("groups"));
- }
- when(policyItem.getGroups()).thenReturn(groupsList);
-
- String[] accesses = (String[])map.get("accesses");;
- Boolean[] isAllowedFlags = (Boolean[])map.get("isAllowed");
- List<RangerPolicyItemAccess> accessesList = null;
- if (accesses != null && isAllowedFlags != null) {
- accessesList = new ArrayList<RangerPolicyItemAccess>();
- for (int i = 0; i < accesses.length; i++) {
- String access = accesses[i];
- Boolean isAllowed = isAllowedFlags[i];
- RangerPolicyItemAccess itemAccess = mock(RangerPolicyItemAccess.class);
- when(itemAccess.getType()).thenReturn(access);
- when(itemAccess.getIsAllowed()).thenReturn(isAllowed);
- accessesList.add(itemAccess);
- }
- }
- when(policyItem.getAccesses()).thenReturn(accessesList);
-
- policyItems.add(policyItem);
- }
- return policyItems;
- }
-
- List<RangerResourceDef> createResourceDefs(Object[][] data) {
- // if data itself is null then return null back
- if (data == null) {
- return null;
- }
- List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
- for (Object[] row : data) {
- RangerResourceDef aDef = null;
- if (row != null) {
- String name = null;
- Boolean mandatory = null;
- String regExPattern = null;
- Boolean isExcludesSupported = null;
- Boolean isRecursiveSupported = null;
- switch(row.length) {
- case 5:
- isRecursiveSupported = (Boolean)row[4];
- case 4:
- isExcludesSupported = (Boolean)row[3];
- case 3:
- regExPattern = (String)row[2];
- case 2:
- mandatory = (Boolean)row[1];
- case 1:
- name = (String)row[0];
- }
- aDef = mock(RangerResourceDef.class);
- when(aDef.getName()).thenReturn(name);
- when(aDef.getMandatory()).thenReturn(mandatory);
- when(aDef.getValidationRegEx()).thenReturn(regExPattern);
- when(aDef.getExcludesSupported()).thenReturn(isExcludesSupported);
- when(aDef.getRecursiveSupported()).thenReturn(isRecursiveSupported);
- }
- defs.add(aDef);
- }
- return defs;
- }
-
- List<RangerResourceDef> createResourceDefs2(Object[][] data) {
- // if data itself is null then return null back
- if (data == null) {
- return null;
- }
- List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
- for (Object[] row : data) {
- RangerResourceDef aDef = null;
- if (row != null) {
- String name = null;
- Boolean isExcludesSupported = null;
- Boolean isRecursiveSupported = null;
- switch(row.length) {
- case 3:
- isRecursiveSupported = (Boolean)row[2]; // note: falls through to next case
- case 2:
- isExcludesSupported = (Boolean)row[1]; // note: falls through to next case
- case 1:
- name = (String)row[0];
- }
- aDef = mock(RangerResourceDef.class);
- when(aDef.getName()).thenReturn(name);
- when(aDef.getExcludesSupported()).thenReturn(isExcludesSupported);
- when(aDef.getRecursiveSupported()).thenReturn(isRecursiveSupported);
- }
- defs.add(aDef);
- }
- return defs;
- }
-
- List<RangerResourceDef> createResourceDefsWithRegEx(String[][] data) {
- // if data itself is null then return null back
- if (data == null) {
- return null;
- }
- List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
- for (String[] row : data) {
- RangerResourceDef aDef = null;
- if (row != null) {
- String name = row[0];
- String regEx = row[1];
- aDef = mock(RangerResourceDef.class);
- when(aDef.getName()).thenReturn(name);
- when(aDef.getValidationRegEx()).thenReturn(regEx);
- }
- defs.add(aDef);
- }
- return defs;
- }
-
- Map<String, RangerPolicyResource> createPolicyResourceMap2(Object[][] input) {
- if (input == null) {
- return null;
- }
- Map<String, RangerPolicyResource> result = new HashMap<String, RangerPolicyResource>(input.length);
- for (Object[] row : input) {
- String resourceName = (String)row[0];
- Boolean isExcludes = (Boolean)row[1];
- Boolean isRecursive = (Boolean)row[2];
- RangerPolicyResource aResource = mock(RangerPolicyResource.class);
- when(aResource.getIsExcludes()).thenReturn(isExcludes);
- when(aResource.getIsRecursive()).thenReturn(isRecursive);
- result.put(resourceName, aResource);
- }
- return result;
- }
-
- List<RangerEnumElementDef> createEnumElementDefs(String[] input) {
- if (input == null) {
- return null;
- }
- List<RangerEnumElementDef> output = new ArrayList<RangerEnumElementDef>();
- for (String elementName : input) {
- RangerEnumElementDef aDef = mock(RangerEnumElementDef.class);
- when(aDef.getName()).thenReturn(elementName);
- output.add(aDef);
- }
- return output;
- }
-
- List<RangerEnumDef> createEnumDefs(Map<String, String[]> input) {
- if (input == null) {
- return null;
- }
- List<RangerEnumDef> defs = new ArrayList<RangerEnumDef>();
- for (Map.Entry<String, String[]> entry : input.entrySet()) {
- RangerEnumDef enumDef = mock(RangerEnumDef.class);
- String enumName = entry.getKey();
- if ("null".equals(enumName)) { // special handling to process null hint in enum-name
- enumName = null;
- }
- when(enumDef.getName()).thenReturn(enumName);
- List<RangerEnumElementDef> elements = createEnumElementDefs(entry.getValue());
- when(enumDef.getElements()).thenReturn(elements);
- // by default set default index to last element
- when(enumDef.getDefaultIndex()).thenReturn(elements.size() - 1);
- defs.add(enumDef);
- }
- return defs;
- }
-
- Map<String, RangerPolicyResource> createPolicyResourceMap(Object[][] input) {
- if (input == null) {
- return null;
- }
- Map<String, RangerPolicyResource> result = new HashMap<String, RangerPolicyResource>(input.length);
- for (Object[] row : input) {
- String resourceName = (String)row[0];
- String[] valuesArray = (String[])row[1];
- Boolean isExcludes = (Boolean)row[2];
- Boolean isRecursive = (Boolean)row[3];
- RangerPolicyResource aResource = mock(RangerPolicyResource.class);
- if (valuesArray == null) {
- when(aResource.getValues()).thenReturn(null);
- } else {
- when(aResource.getValues()).thenReturn(Arrays.asList(valuesArray));
- }
- when(aResource.getIsExcludes()).thenReturn(isExcludes);
- when(aResource.getIsRecursive()).thenReturn(isRecursive);
- result.put(resourceName, aResource);
- }
- return result;
- }
-}
[2/4] incubator-ranger git commit: RANGER-278 move validation classes
under org.apache.ranger.plugin.model.validation
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
deleted file mode 100644
index 21d14e2..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
+++ /dev/null
@@ -1,496 +0,0 @@
-package org.apache.ranger.rest;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.collections.CollectionUtils;
-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;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-
-import com.google.common.collect.Sets;
-
-public class RangerPolicyValidator extends RangerValidator {
-
- private static final Log LOG = LogFactory.getLog(RangerPolicyValidator.class);
-
- public RangerPolicyValidator(ServiceStore store) {
- super(store);
- }
-
- public void validate(RangerPolicy policy, Action action) throws Exception {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerPolicyValidator.validate(%s, %s)", policy, action));
- }
-
- List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
- boolean valid = isValid(policy, action, failures);
- String message = "";
- try {
- if (!valid) {
- message = serializeFailures(failures);
- throw new Exception(message);
- }
- } finally {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerPolicyValidator.validate(%s, %s): %s, reason[%s]", policy, action, valid, message));
- }
- }
- }
-
- @Override
- boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", id, action, failures));
- }
-
- boolean valid = true;
- if (action != Action.DELETE) {
- failures.add(new ValidationFailureDetailsBuilder()
- .isAnInternalError()
- .becauseOf("isValid(Long) is only supported for DELETE")
- .build());
- valid = false;
- } else if (id == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isMissing()
- .build());
- valid = false;
- } else if (getPolicy(id) == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isSemanticallyIncorrect()
- .becauseOf("no policy found for id[" + id + "]")
- .build());
- valid = false;
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", id, action, failures, valid));
- }
- return valid;
- }
-
- boolean isValid(RangerPolicy policy, Action action, List<ValidationFailureDetails> failures) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policy, action, failures));
- }
-
- if (!(action == Action.CREATE || action == Action.UPDATE)) {
- throw new IllegalArgumentException("isValid(RangerPolicy, ...) is only supported for create/update");
- }
- boolean valid = true;
- if (policy == null) {
- String message = "policy object passed in was null";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy")
- .isMissing()
- .becauseOf(message)
- .build());
- valid = false;
- } else {
- Long id = policy.getId();
- if (action == Action.UPDATE) { // id is ignored for CREATE
- if (id == null) {
- String message = "policy id was null/empty/blank";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isMissing()
- .becauseOf(message)
- .build());
- valid = false;
- } else if (getPolicy(id) == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isSemanticallyIncorrect()
- .becauseOf("no policy exists with id[" + id +"]")
- .build());
- valid = false;
- }
- }
- String policyName = policy.getName();
- String serviceName = policy.getService();
- if (StringUtils.isBlank(policyName)) {
- String message = "policy name was null/empty/blank[" + policyName + "]";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("name")
- .isMissing()
- .becauseOf(message)
- .build());
- valid = false;
- } else {
- List<RangerPolicy> policies = getPolicies(policyName, serviceName);
- if (CollectionUtils.isNotEmpty(policies)) {
- if (policies.size() > 1) {
- failures.add(new ValidationFailureDetailsBuilder()
- .isAnInternalError()
- .becauseOf("multiple policies found with the name[" + policyName + "]")
- .build());
- valid = false;
- } else if (action == Action.CREATE) { // size == 1
- failures.add(new ValidationFailureDetailsBuilder()
- .field("name")
- .isSemanticallyIncorrect()
- .becauseOf("policy already exists with name[" + policyName + "]; its id is[" + policies.iterator().next().getId() + "]")
- .build());
- valid = false;
- } else if (policies.iterator().next().getId() != id) { // size == 1 && action == UPDATE
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id/name")
- .isSemanticallyIncorrect()
- .becauseOf("id/name conflict: another policy already exists with name[" + policyName + "], its id is[" + policies.iterator().next().getId() + "]")
- .build());
- valid = false;
- }
- }
- }
- RangerService service = null;
- if (StringUtils.isBlank(serviceName)) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("service")
- .isMissing()
- .becauseOf("service name was null/empty/blank")
- .build());
- valid = false;
- } else {
- service = getService(serviceName);
- if (service == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("service")
- .isMissing()
- .becauseOf("service name was null/empty/blank")
- .build());
- valid = false;
- }
- }
- List<RangerPolicyItem> policyItems = policy.getPolicyItems();
- boolean isAuditEnabled = getIsAuditEnabled(policy);
- RangerServiceDef serviceDef = null;
- String serviceDefName = null;
- if (CollectionUtils.isEmpty(policyItems) && !isAuditEnabled) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy items")
- .isMissing()
- .becauseOf("at least one policy item must be specified if audit isn't enabled")
- .build());
- valid = false;
- } else if (service != null) {
- serviceDefName = service.getType();
- serviceDef = getServiceDef(serviceDefName);
- if (serviceDef == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy service def")
- .isAnInternalError()
- .becauseOf("Service def of policies service does not exist")
- .build());
- valid = false;
- } else {
- valid = isValidPolicyItems(policyItems, failures, serviceDef) && valid;
- }
- }
- if (serviceDef != null) {
- Set<String> mandatoryResources = getMandatoryResourceNames(serviceDef);
- Set<String> policyResources = getPolicyResources(policy);
- Set<String> missingResources = Sets.difference(mandatoryResources, policyResources);
- if (!missingResources.isEmpty()) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("resources")
- .subField(missingResources.iterator().next()) // we return any one parameter!
- .isMissing()
- .becauseOf("required resources[" + missingResources + "] are missing")
- .build());
- valid = false;
- }
- Set<String> allResource = getAllResourceNames(serviceDef);
- Set<String> unknownResources = Sets.difference(policyResources, allResource);
- if (!unknownResources.isEmpty()) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("resources")
- .subField(unknownResources.iterator().next()) // we return any one parameter!
- .isSemanticallyIncorrect()
- .becauseOf("resource[" + unknownResources + "] is not valid for service-def[" + serviceDefName + "]")
- .build());
- valid = false;
- }
- Map<String, RangerPolicyResource> resourceMap = policy.getResources();
- valid = isValidResourceValues(resourceMap, failures, serviceDef) && valid;
- valid = isValidResourceFlags(resourceMap, failures, serviceDef.getResources(), serviceDefName, policyName) && valid;
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policy, action, failures, valid));
- }
- return valid;
- }
-
- boolean isValidResourceFlags(final Map<String, RangerPolicyResource> inputPolicyResources, final List<ValidationFailureDetails> failures,
- final List<RangerResourceDef> resourceDefs, final String serviceDefName, final String policyName) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s)", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName));
- }
-
- boolean valid = true;
- if (inputPolicyResources == null) {
- LOG.debug("isValidResourceFlags: resourceMap is null");
- } else if (resourceDefs == null) {
- LOG.debug("isValidResourceFlags: service Def is null");
- } else {
- Map<String, RangerPolicyResource> policyResources = getPolicyResourceWithLowerCaseKeys(inputPolicyResources);
- for (RangerResourceDef resourceDef : resourceDefs) {
- if (resourceDef == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("resource-def")
- .isAnInternalError()
- .becauseOf("a resource-def on resource def collection of service-def[" + serviceDefName + "] was null")
- .build());
- valid = false;
- } else if (StringUtils.isBlank(resourceDef.getName())) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("resource-def-name")
- .isAnInternalError()
- .becauseOf("name of a resource-def on resource def collection of service-def[" + serviceDefName + "] was null")
- .build());
- valid = false;
- } else {
- String resourceName = resourceDef.getName().toLowerCase();
- RangerPolicyResource policyResource = policyResources.get(resourceName);
- if (policyResource == null) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("a policy-resource object for resource[" + resourceName + "] on policy [" + policyName + "] was null");
- }
- } else {
- boolean excludesSupported = Boolean.TRUE.equals(resourceDef.getExcludesSupported()); // could be null
- boolean policyIsExcludes = Boolean.TRUE.equals(policyResource.getIsExcludes()); // could be null
- if (policyIsExcludes && !excludesSupported) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("isExcludes")
- .subField(resourceName)
- .isSemanticallyIncorrect()
- .becauseOf("isExcludes specified as [" + policyIsExcludes + "] for resource [" + resourceName + "] which doesn't support isExcludes")
- .build());
- valid = false;
- }
- boolean recursiveSupported = Boolean.TRUE.equals(resourceDef.getRecursiveSupported());
- boolean policyIsRecursive = Boolean.TRUE.equals(policyResource.getIsRecursive());
- if (policyIsRecursive && !recursiveSupported) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("isRecursive")
- .subField(resourceName)
- .isSemanticallyIncorrect()
- .becauseOf("isRecursive specified as [" + policyIsRecursive + "] for resource [" + resourceName + "] which doesn't support isRecursive")
- .build());
- valid = false;
- }
- }
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s): %s", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName, valid));
- }
- return valid;
- }
-
- boolean isValidResourceValues(Map<String, RangerPolicyResource> resourceMap, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerPolicyValidator.isValidResourceValues(%s, %s, %s)", resourceMap, failures, serviceDef));
- }
-
- boolean valid = true;
- if (resourceMap == null) {
- LOG.debug("isValidResourceValues: resourceMap is null");
- } else if (serviceDef == null) {
- LOG.debug("isValidResourceValues: service Def is null");
- } else {
- Map<String, String> validationRegExMap = getValidationRegExes(serviceDef);
- for (Map.Entry<String, RangerPolicyResource> entry : resourceMap.entrySet()) {
- String name = entry.getKey();
- RangerPolicyResource policyResource = entry.getValue();
- if (validationRegExMap.containsKey(name) && policyResource != null && CollectionUtils.isNotEmpty(policyResource.getValues())) {
- String regEx = validationRegExMap.get(name);
- for (String aValue : policyResource.getValues()) {
- if (StringUtils.isBlank(aValue)) {
- LOG.debug("resource value was blank");
- } else if (!aValue.matches(regEx)) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("resource-values")
- .subField(name)
- .isSemanticallyIncorrect()
- .becauseOf("resources value[" + aValue + "] does not match validation regex[" + regEx + "] defined on service-def[" + serviceDef.getName() + "]")
- .build());
- valid = false;
- }
- }
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerPolicyValidator.isValidResourceValues(%s, %s, %s): %s", resourceMap, failures, serviceDef, valid));
- }
- return valid;
- }
-
- boolean isValidPolicyItems(List<RangerPolicyItem> policyItems, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policyItems, failures, serviceDef));
- }
-
- boolean valid = true;
- if (CollectionUtils.isEmpty(policyItems)) {
- LOG.debug("policy items collection was null/empty");
- } else {
- for (RangerPolicyItem policyItem : policyItems) {
- if (policyItem == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy item")
- .isMissing()
- .becauseOf("policy items object was null")
- .build());
- valid = false;
- } else {
- // we want to go through all elements even though one may be bad so all failures are captured
- valid = isValidPolicyItem(policyItem, failures, serviceDef) && valid;
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItems, failures, serviceDef, valid));
- }
- return valid;
- }
-
- boolean isValidPolicyItem(RangerPolicyItem policyItem, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policyItem, failures, serviceDef));
- }
-
- boolean valid = true;
- if (policyItem == null) {
- LOG.debug("policy item was null!");
- } else {
- // access items collection can't be empty and should be otherwise valid
- if (CollectionUtils.isEmpty(policyItem.getAccesses())) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy item accesses")
- .isMissing()
- .becauseOf("policy items accesses collection was null")
- .build());
- valid = false;
- } else {
- valid = isValidItemAccesses(policyItem.getAccesses(), failures, serviceDef) && valid;
- }
- // both users and user-groups collections can't be empty
- if (CollectionUtils.isEmpty(policyItem.getUsers()) && CollectionUtils.isEmpty(policyItem.getGroups())) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy item users/user-groups")
- .isMissing()
- .becauseOf("both users and user-groups collections on the policy item were null/empty")
- .build());
- valid = false;
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItem, failures, serviceDef, valid));
- }
- return valid;
- }
-
- boolean isValidItemAccesses(List<RangerPolicyItemAccess> accesses, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", accesses, failures, serviceDef));
- }
-
- boolean valid = true;
- if (CollectionUtils.isEmpty(accesses)) {
- LOG.debug("policy item accesses collection was null/empty!");
- } else {
- Set<String> accessTypes = getAccessTypes(serviceDef);
- for (RangerPolicyItemAccess access : accesses) {
- if (access == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy item access")
- .isMissing()
- .becauseOf("policy items access object was null")
- .build());
- valid = false;
- } else {
- // we want to go through all elements even though one may be bad so all failures are captured
- valid = isValidPolicyItemAccess(access, failures, accessTypes) && valid;
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s): %s", accesses, failures, serviceDef, valid));
- }
- return valid;
- }
-
- boolean isValidPolicyItemAccess(RangerPolicyItemAccess access, List<ValidationFailureDetails> failures, Set<String> accessTypes) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s)", access, failures, accessTypes));
- }
-
- boolean valid = true;
- if (CollectionUtils.isEmpty(accessTypes)) { // caller should firewall this argument!
- LOG.debug("isValidPolicyItemAccess: accessTypes was null!");
- } else if (access == null) {
- LOG.debug("isValidPolicyItemAccess: policy item access was null!");
- } else {
- String accessType = access.getType();
- if (StringUtils.isBlank(accessType)) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy item access type")
- .isMissing()
- .becauseOf("policy items access type's name was null/empty/blank")
- .build());
- valid = false;
- } else if (!accessTypes.contains(accessType.toLowerCase())) {
- String message = String.format("access type[%s] not among valid types for service[%s]", accessType, accessTypes);
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy item access type")
- .isSemanticallyIncorrect()
- .becauseOf(message)
- .build());
- valid = false;
- }
- Boolean isAllowed = access.getIsAllowed();
- // it can be null (which is treated as allowed) but not false
- if (isAllowed != null && isAllowed == false) {
- String message = "access type is set to deny. Currently deny access types are not supported.";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("policy item access type allowed")
- .isSemanticallyIncorrect()
- .becauseOf(message)
- .build());
- valid = false;
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s): %s", access, failures, accessTypes, valid));
- }
- return valid;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
deleted file mode 100644
index a84f68a..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
+++ /dev/null
@@ -1,365 +0,0 @@
-package org.apache.ranger.rest;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-
-import com.google.common.collect.Sets;
-
-public class RangerServiceDefValidator extends RangerValidator {
-
- private static final Log LOG = LogFactory.getLog(RangerServiceDefValidator.class);
-
- public RangerServiceDefValidator(ServiceStore store) {
- super(store);
- }
-
- public void validate(final RangerServiceDef serviceDef, final Action action) throws Exception {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerServiceDefValidator.validate(%s, %s)", serviceDef, action));
- }
-
- List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
- boolean valid = isValid(serviceDef, action, failures);
- String message = "";
- try {
- if (!valid) {
- message = serializeFailures(failures);
- throw new Exception(message);
- }
- } finally {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerServiceDefValidator.validate(%s, %s): %s, reason[%s]", serviceDef, action, valid, message));
- }
- }
- }
-
- boolean isValid(final Long id, final Action action, final List<ValidationFailureDetails> failures) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerServiceDefValidator.isValid(" + id + ")");
- }
-
- boolean valid = true;
- if (action != Action.DELETE) {
- failures.add(new ValidationFailureDetailsBuilder()
- .isAnInternalError()
- .becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
- .build());
- valid = false;
- } else if (id == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isMissing()
- .build());
- valid = false;
- } else if (getServiceDef(id) == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isSemanticallyIncorrect()
- .becauseOf("no service def found for id[" + id + "]")
- .build());
- valid = false;
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerServiceDefValidator.isValid(" + id + "): " + valid);
- }
- return valid;
- }
-
- boolean isValid(final RangerServiceDef serviceDef, final Action action, final List<ValidationFailureDetails> failures) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerServiceDefValidator.isValid(" + serviceDef + ")");
- }
-
- if (!(action == Action.CREATE || action == Action.UPDATE)) {
- throw new IllegalArgumentException("isValid(RangerServiceDef, ...) is only supported for CREATE/UPDATE");
- }
- boolean valid = true;
- if (serviceDef == null) {
- String message = "service def object passed in was null";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("service def")
- .isMissing()
- .becauseOf(message)
- .build());
- valid = false;
- } else {
- Long id = serviceDef.getId();
- if (action == Action.UPDATE) { // id is ignored for CREATE
- if (id == null) {
- String message = "service def id was null/empty/blank";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isMissing()
- .becauseOf(message)
- .build());
- valid = false;
- } else if (getServiceDef(id) == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isSemanticallyIncorrect()
- .becauseOf("no service def exists with id[" + id +"]")
- .build());
- valid = false;
- }
- }
- // validate the service def name
- String name = serviceDef.getName();
- boolean nameSpecified = StringUtils.isNotBlank(name);
- if (!nameSpecified) {
- String message = "service def name[" + name + "] was null/empty/blank";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("name")
- .isMissing()
- .becauseOf(message)
- .build());
- valid = false;
- } else {
- RangerServiceDef otherServiceDef = getServiceDef(name);
- if (otherServiceDef != null && action == Action.CREATE) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("name")
- .isSemanticallyIncorrect()
- .becauseOf("service def with the name[" + name + "] already exists")
- .build());
- valid = false;
- } else if (otherServiceDef != null && otherServiceDef.getId() !=null && otherServiceDef.getId() != id) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id/name")
- .isSemanticallyIncorrect()
- .becauseOf("id/name conflict: another service def already exists with name[" + name + "], its id is [" + otherServiceDef.getId() + "]")
- .build());
- valid = false;
- }
- }
- if (CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("access types")
- .isMissing()
- .becauseOf("access types collection was null/empty")
- .build());
- valid = false;
- } else {
- valid = isValidAccessTypes(serviceDef.getAccessTypes(), failures) && valid;
- }
- if (CollectionUtils.isEmpty(serviceDef.getEnums())) {
- LOG.debug("No enums specified on the service def. Ok!");
- } else {
- valid = isValidEnums(serviceDef.getEnums(), failures) && valid;
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerServiceDefValidator.isValid(" + serviceDef + "): " + valid);
- }
- return valid;
- }
-
- boolean isValidAccessTypes(final List<RangerAccessTypeDef> accessTypeDefs, final List<ValidationFailureDetails> failures) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerServiceDefValidator.isValidAccessTypes(%s, %s)", accessTypeDefs, failures));
- }
-
- boolean valid = true;
- if (CollectionUtils.isEmpty(accessTypeDefs)) {
- LOG.debug("access type def collection is empty/null");
- } else {
- List<RangerAccessTypeDef> defsWithImpliedGrants = new ArrayList<RangerAccessTypeDef>();
- Set<String> accessNames = new HashSet<String>();
- for (RangerAccessTypeDef def : accessTypeDefs) {
- String name = def.getName();
- // name can't be null/empty/blank
- if (StringUtils.isBlank(name)) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("access type name")
- .isMissing()
- .becauseOf("access type name[" + name + "] is null/empty")
- .build());
- valid = false;
- } else if (accessNames.contains(name.toLowerCase())) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("access type name")
- .subField(name)
- .isSemanticallyIncorrect()
- .becauseOf("duplicate access type names in access types collection: [" + name + "]")
- .build());
- valid = false;
- } else {
- accessNames.add(name.toLowerCase()); // we have a new unique access type
- }
- if (CollectionUtils.isNotEmpty(def.getImpliedGrants())) {
- defsWithImpliedGrants.add(def);
- }
- }
- // validate implied grants
- for (RangerAccessTypeDef def : defsWithImpliedGrants) {
- Collection<String> impliedGrants = getImpliedGrants(def);
- Set<String> unknownAccessTypes = Sets.difference(Sets.newHashSet(impliedGrants), accessNames);
- if (!unknownAccessTypes.isEmpty()) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("implied grants")
- .subField(unknownAccessTypes.iterator().next()) // we return just on item here. Message has all unknow items
- .isSemanticallyIncorrect()
- .becauseOf("implied grant[" + impliedGrants + "] contains an unknown access types[" + unknownAccessTypes + "]")
- .build());
- valid = false;
- }
- // implied grant should not imply itself!
- String name = def.getName(); // note: this name could be null/blank/empty!
- if (impliedGrants.contains(name)) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("implied grants")
- .subField(name)
- .isSemanticallyIncorrect()
- .becauseOf("implied grants list [" + impliedGrants + "] for access type[" + name + "] contains itself")
- .build());
- valid = false;
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerServiceDefValidator.isValidAccessTypes(%s, %s): %s", accessTypeDefs, failures, valid));
- }
- return valid;
- }
-
- boolean isValidEnums(List<RangerEnumDef> enumDefs, List<ValidationFailureDetails> failures) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumDefs, failures));
- }
-
- boolean valid = true;
- if (CollectionUtils.isEmpty(enumDefs)) {
- LOG.debug("enum def collection passed in was null/empty");
- } else {
- Set<String> enumNames = new HashSet<String>();
- for (RangerEnumDef enumDef : enumDefs) {
- if (enumDef == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("enum def")
- .isMissing()
- .becauseOf("An enum def in enums collection is null")
- .build());
- valid = false;
- } else {
- // enum-names must non-blank and be unique to a service definition
- String enumName = enumDef.getName();
- if (StringUtils.isBlank(enumName)) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("enum def name")
- .isMissing()
- .becauseOf("enum name [" + enumName + "] is null/empty")
- .build());
- valid = false;
- } else if (enumNames.contains(enumName.toLowerCase())) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("enum def name")
- .subField(enumName)
- .isSemanticallyIncorrect()
- .becauseOf("dumplicate enum name [" + enumName + "] found")
- .build());
- valid = false;
- } else {
- enumNames.add(enumName.toLowerCase());
- }
- // enum must contain at least one valid value and those values should be non-blank and distinct
- if (CollectionUtils.isEmpty(enumDef.getElements())) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("enum values")
- .subField(enumName)
- .isMissing()
- .becauseOf("enum [" + enumName + "] does not have any elements")
- .build());
- valid = false;
- } else {
- valid = isValidEnumElements(enumDef.getElements(), failures, enumName) && valid;
- // default index should be valid
- int defaultIndex = getEnumDefaultIndex(enumDef);
- if (defaultIndex < 0 || defaultIndex >= enumDef.getElements().size()) { // max index is one less than the size of the elements list
- failures.add(new ValidationFailureDetailsBuilder()
- .field("enum default index")
- .subField(enumName)
- .isSemanticallyIncorrect()
- .becauseOf("default index[" + defaultIndex + "] for enum [" + enumName + "] is invalid")
- .build());
- valid = false;
- }
- }
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumDefs, failures, valid));
- }
- return valid;
- }
-
- boolean isValidEnumElements(List<RangerEnumElementDef> enumElementsDefs, List<ValidationFailureDetails> failures, String enumName) {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumElementsDefs, failures));
- }
-
- boolean valid = true;
- if (CollectionUtils.isEmpty(enumElementsDefs)) {
- LOG.debug("Enum elements list passed in was null/empty!");
- } else {
- // enum element names should be valid and distinct
- Set<String> elementNames = new HashSet<String>();
- for (RangerEnumElementDef elementDef : enumElementsDefs) {
- if (elementDef == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("enum element")
- .subField(enumName)
- .isMissing()
- .becauseOf("An enum element in enum element collection of enum [" + enumName + "] is null")
- .build());
- valid = false;
- } else {
- String elementName = elementDef.getName();
- if (StringUtils.isBlank(elementName)) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("enum element name")
- .subField(enumName)
- .isMissing()
- .becauseOf("Name of an element of enum [" + enumName + "] is null/empty[" + elementName + "]")
- .build());
- valid = false;
- } else if (elementNames.contains(elementName.toLowerCase())) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("enum element name")
- .subField(enumName)
- .isSemanticallyIncorrect()
- .becauseOf("dumplicate enum element name [" + elementName + "] found for enum[" + enumName + "]")
- .build());
- valid = false;
- } else {
- elementNames.add(elementName.toLowerCase());
- }
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumElementsDefs, failures, valid));
- }
- return valid;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
deleted file mode 100644
index 3a55638..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.rest;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-
-import com.google.common.collect.Sets;
-
-public class RangerServiceValidator extends RangerValidator {
-
- private static final Log LOG = LogFactory.getLog(RangerServiceValidator.class);
-
- public RangerServiceValidator(ServiceStore store) {
- super(store);
- }
-
- public void validate(RangerService service, Action action) throws Exception {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("==> RangerServiceValidator.validate(%s, %s)", service, action));
- }
-
- List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
- boolean valid = isValid(service, action, failures);
- String message = "";
- try {
- if (!valid) {
- message = serializeFailures(failures);
- throw new Exception(message);
- }
- } finally {
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("<== RangerServiceValidator.validate(%s, %s): %s, reason[%s]", service, action, valid, message));
- }
- }
- }
-
- boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerServiceValidator.isValid(" + id + ")");
- }
-
- boolean valid = true;
- if (action != Action.DELETE) {
- failures.add(new ValidationFailureDetailsBuilder()
- .isAnInternalError()
- .becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
- .build());
- valid = false;
- } else if (id == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isMissing()
- .build());
- valid = false;
- } else if (getService(id) == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isSemanticallyIncorrect()
- .becauseOf("no service found for id[" + id + "]")
- .build());
- valid = false;
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerServiceValidator.isValid(" + id + "): " + valid);
- }
- return valid;
- }
-
- boolean isValid(RangerService service, Action action, List<ValidationFailureDetails> failures) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerServiceValidator.isValid(" + service + ")");
- }
- if (!(action == Action.CREATE || action == Action.UPDATE)) {
- throw new IllegalArgumentException("isValid(RangerService, ...) is only supported for CREATE/UPDATE");
- }
-
- boolean valid = true;
- if (service == null) {
- String message = "service object passed in was null";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("service")
- .isMissing()
- .becauseOf(message)
- .build());
- valid = false;
- } else {
- Long id = service.getId();
- if (action == Action.UPDATE) { // id is ignored for CREATE
- if (id == null) {
- String message = "service id was null/empty/blank";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isMissing()
- .becauseOf(message)
- .build());
- valid = false;
- } else if (getService(id) == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id")
- .isSemanticallyIncorrect()
- .becauseOf("no service exists with id[" + id +"]")
- .build());
- valid = false;
- }
- }
- String name = service.getName();
- boolean nameSpecified = StringUtils.isNotBlank(name);
- RangerServiceDef serviceDef = null;
- if (!nameSpecified) {
- String message = "service name[" + name + "] was null/empty/blank";
- LOG.debug(message);
- failures.add(new ValidationFailureDetailsBuilder()
- .field("name")
- .isMissing()
- .becauseOf(message)
- .build());
- valid = false;
- } else {
- RangerService otherService = getService(name);
- if (otherService != null && action == Action.CREATE) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("name")
- .isSemanticallyIncorrect()
- .becauseOf("service with the name[" + name + "] already exists")
- .build());
- valid = false;
- } else if (otherService != null && otherService.getId() !=null && otherService.getId() != id) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("id/name")
- .isSemanticallyIncorrect()
- .becauseOf("id/name conflict: another service already exists with name[" + name + "], its id is [" + otherService.getId() + "]")
- .build());
- valid = false;
- }
- }
- String type = service.getType();
- boolean typeSpecified = StringUtils.isNotBlank(type);
- if (!typeSpecified) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("type")
- .isMissing()
- .becauseOf("service def [" + type + "] was null/empty/blank")
- .build());
- valid = false;
- } else {
- serviceDef = getServiceDef(type);
- if (serviceDef == null) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("type")
- .isSemanticallyIncorrect()
- .becauseOf("service def named[" + type + "] not found")
- .build());
- valid = false;
- }
- }
- if (nameSpecified && serviceDef != null) {
- // check if required parameters were specified
- Set<String> reqiredParameters = getRequiredParameters(serviceDef);
- Set<String> inputParameters = getServiceConfigParameters(service);
- Set<String> missingParameters = Sets.difference(reqiredParameters, inputParameters);
- if (!missingParameters.isEmpty()) {
- failures.add(new ValidationFailureDetailsBuilder()
- .field("configuration")
- .subField(missingParameters.iterator().next()) // we return any one parameter!
- .isMissing()
- .becauseOf("required configuration parameter is missing; missing parameters: " + missingParameters)
- .build());
- valid = false;
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerServiceValidator.isValid(" + service + "): " + valid);
- }
- return valid;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
deleted file mode 100644
index dc8ea65..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * 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.rest;
-
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.collections.CollectionUtils;
-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;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.plugin.util.SearchFilter;
-
-public abstract class RangerValidator {
-
- private static final Log LOG = LogFactory.getLog(RangerValidator.class);
-
- ServiceStore _store;
-
- public enum Action {
- CREATE, UPDATE, DELETE;
- };
-
- protected RangerValidator(ServiceStore store) {
- if (store == null) {
- throw new IllegalArgumentException("ServiceValidator(): store is null!");
- }
- _store = store;
- }
-
- public void validate(Long id, Action action) throws Exception {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.validate(" + id + ")");
- }
-
- List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
- if (isValid(id, action, failures)) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.validate(" + id + "): valid");
- }
- } else {
- String message = serializeFailures(failures);
- LOG.debug("<== RangerValidator.validate(" + id + "): invalid, reason[" + message + "]");
- throw new Exception(message);
- }
- }
-
- /**
- * This method is expected to be overridden by sub-classes. Default implementation provided to not burden implementers from having to implement methods that they know would never be called.
- * @param id
- * @param action
- * @param failures
- * @return
- */
- boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
- failures.add(new ValidationFailureDetailsBuilder()
- .isAnInternalError()
- .becauseOf("unimplemented method called")
- .build());
- return false;
- }
-
- String serializeFailures(List<ValidationFailureDetails> failures) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getFailureMessage()");
- }
-
- String message = null;
- if (CollectionUtils.isEmpty(failures)) {
- LOG.warn("serializeFailures: called while list of failures is null/empty!");
- } else {
- StringBuilder builder = new StringBuilder();
- for (ValidationFailureDetails aFailure : failures) {
- builder.append(aFailure.toString());
- builder.append(";");
- }
- message = builder.toString();
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.serializeFailures(): " + message);
- }
- return message;
- }
-
- Set<String> getServiceConfigParameters(RangerService service) {
- if (service == null || service.getConfigs() == null) {
- return new HashSet<String>();
- } else {
- return service.getConfigs().keySet();
- }
- }
-
- Set<String> getRequiredParameters(RangerServiceDef serviceDef) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getRequiredParameters(" + serviceDef + ")");
- }
-
- Set<String> result;
- if (serviceDef == null) {
- result = Collections.emptySet();
- } else {
- List<RangerServiceConfigDef> configs = serviceDef.getConfigs();
- if (CollectionUtils.isEmpty(configs)) {
- result = Collections.emptySet();
- } else {
- result = new HashSet<String>(configs.size()); // at worse all of the config items are required!
- for (RangerServiceConfigDef configDef : configs) {
- if (configDef.getMandatory()) {
- result.add(configDef.getName());
- }
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getRequiredParameters(" + serviceDef + "): " + result);
- }
- return result;
- }
-
- RangerServiceDef getServiceDef(Long id) {
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getServiceDef(" + id + ")");
- }
- RangerServiceDef result = null;
- try {
- result = _store.getServiceDef(id);
- } catch (Exception e) {
- LOG.debug("Encountred exception while retrieving service def from service store!", e);
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getServiceDef(" + id + "): " + result);
- }
- return result;
- }
-
- RangerServiceDef getServiceDef(String type) {
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getServiceDef(" + type + ")");
- }
- RangerServiceDef result = null;
- try {
- result = _store.getServiceDefByName(type);
- } catch (Exception e) {
- LOG.debug("Encountred exception while retrieving service definition from service store!", e);
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getServiceDef(" + type + "): " + result);
- }
- return result;
- }
-
- RangerService getService(Long id) {
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getService(" + id + ")");
- }
- RangerService result = null;
- try {
- result = _store.getService(id);
- } catch (Exception e) {
- LOG.debug("Encountred exception while retrieving service from service store!", e);
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getService(" + id + "): " + result);
- }
- return result;
- }
-
- RangerService getService(String name) {
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getService(" + name + ")");
- }
- RangerService result = null;
- try {
- result = _store.getServiceByName(name);
- } catch (Exception e) {
- LOG.debug("Encountred exception while retrieving service from service store!", e);
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getService(" + name + "): " + result);
- }
- return result;
- }
-
- RangerPolicy getPolicy(Long id) {
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getPolicy(" + id + ")");
- }
- RangerPolicy result = null;
- try {
- result = _store.getPolicy(id);
- } catch (Exception e) {
- LOG.debug("Encountred exception while retrieving policy from service store!", e);
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getPolicy(" + id + "): " + result);
- }
- return result;
- }
-
- List<RangerPolicy> getPolicies(final String policyName, final String serviceName) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getPolicies(" + policyName + ", " + serviceName + ")");
- }
-
- List<RangerPolicy> policies = null;
- try {
- SearchFilter filter = new SearchFilter();
- filter.setParam(SearchFilter.POLICY_NAME, policyName);
- filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
-
- policies = _store.getPolicies(filter);
- } catch (Exception e) {
- LOG.debug("Encountred exception while retrieving service from service store!", e);
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getPolicies(" + policyName + ", " + serviceName + "): " + policies);
- }
- return policies;
- }
-
- Set<String> getAccessTypes(RangerServiceDef serviceDef) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getAccessTypes(" + serviceDef + ")");
- }
-
- Set<String> accessTypes = new HashSet<String>();
- if (serviceDef == null) {
- LOG.warn("serviceDef passed in was null!");
- } else if (CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
- LOG.warn("AccessTypeDef collection on serviceDef was null!");
- } else {
- for (RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) {
- if (accessTypeDef == null) {
- LOG.warn("Access type def was null!");
- } else {
- String accessType = accessTypeDef.getName();
- if (StringUtils.isBlank(accessType)) {
- LOG.warn("Access type def name was null/empty/blank!");
- } else {
- accessTypes.add(accessType.toLowerCase());
- }
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getAccessTypes(" + serviceDef + "): " + accessTypes);
- }
- return accessTypes;
- }
-
- /**
- * This function exists to encapsulates the current behavior of code which treats and unspecified audit preference to mean audit is enabled.
- * @param policy
- * @return
- */
- boolean getIsAuditEnabled(RangerPolicy policy) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getIsAuditEnabled(" + policy + ")");
- }
-
- boolean isEnabled = false;
- if (policy == null) {
- LOG.warn("policy was null!");
- } else if (policy.getIsAuditEnabled() == null) {
- isEnabled = true;
- } else {
- isEnabled = policy.getIsAuditEnabled();
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getIsAuditEnabled(" + policy + "): " + isEnabled);
- }
- return isEnabled;
- }
-
- /**
- * Returns names of resource types set to lower-case to allow for case-insensitive comparison.
- * @param serviceDef
- * @return
- */
- Set<String> getMandatoryResourceNames(RangerServiceDef serviceDef) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getMandatoryResourceNames(" + serviceDef + ")");
- }
-
- Set<String> resourceNames = new HashSet<String>();
- if (serviceDef == null) {
- LOG.warn("serviceDef passed in was null!");
- } else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
- LOG.warn("ResourceDef collection on serviceDef was null!");
- } else {
- for (RangerResourceDef resourceTypeDef : serviceDef.getResources()) {
- if (resourceTypeDef == null) {
- LOG.warn("resource type def was null!");
- } else {
- Boolean mandatory = resourceTypeDef.getMandatory();
- if (mandatory != null && mandatory == true) {
- String resourceName = resourceTypeDef.getName();
- if (StringUtils.isBlank(resourceName)) {
- LOG.warn("Resource def name was null/empty/blank!");
- } else {
- resourceNames.add(resourceName.toLowerCase());
- }
- }
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getMandatoryResourceNames(" + serviceDef + "): " + resourceNames);
- }
- return resourceNames;
- }
-
- Set<String> getAllResourceNames(RangerServiceDef serviceDef) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("==> RangerValidator.getAllResourceNames(" + serviceDef + ")");
- }
-
- Set<String> resourceNames = new HashSet<String>();
- if (serviceDef == null) {
- LOG.warn("serviceDef passed in was null!");
- } else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
- LOG.warn("ResourceDef collection on serviceDef was null!");
- } else {
- for (RangerResourceDef resourceTypeDef : serviceDef.getResources()) {
- if (resourceTypeDef == null) {
- LOG.warn("resource type def was null!");
- } else {
- String resourceName = resourceTypeDef.getName();
- if (StringUtils.isBlank(resourceName)) {
- LOG.warn("Resource def name was null/empty/blank!");
- } else {
- resourceNames.add(resourceName.toLowerCase());
- }
- }
- }
- }
-
- if(LOG.isDebugEnabled()) {
- LOG.debug("<== RangerValidator.getAllResourceNames(" + serviceDef + "): " + resourceNames);
- }
- return resourceNames;
- }
-
- /**
- * Returns the resource-types defined on the policy converted to lowe-case
- * @param policy
- * @return
- */
- Set<String> getPolicyResources(RangerPolicy policy) {
- if (policy == null || policy.getResources() == null || policy.getResources().isEmpty()) {
- return new HashSet<String>();
- } else {
- Set<String> result = new HashSet<String>();
- for (String name : policy.getResources().keySet()) {
- result.add(name.toLowerCase());
- }
- return result;
- }
- }
-
- Map<String, String> getValidationRegExes(RangerServiceDef serviceDef) {
- if (serviceDef == null || CollectionUtils.isEmpty(serviceDef.getResources())) {
- return new HashMap<String, String>();
- } else {
- Map<String, String> result = new HashMap<String, String>();
- for (RangerResourceDef resourceDef : serviceDef.getResources()) {
- if (resourceDef == null) {
- LOG.warn("A resource def in resource def collection is null");
- } else {
- String name = resourceDef.getName();
- String regEx = resourceDef.getValidationRegEx();
- if (StringUtils.isBlank(name)) {
- LOG.warn("resource name is null/empty/blank");
- } else if (StringUtils.isBlank(regEx)) {
- LOG.debug("validation regex is null/empty/blank");
- } else {
- result.put(name, regEx);
- }
- }
- }
- return result;
- }
- }
-
- int getEnumDefaultIndex(RangerEnumDef enumDef) {
- int index;
- if (enumDef == null) {
- index = -1;
- } else if (enumDef.getDefaultIndex() == null) {
- index = 0;
- } else {
- index = enumDef.getDefaultIndex();
- }
- return index;
- }
-
- Collection<String> getImpliedGrants(RangerAccessTypeDef def) {
- if (def == null) {
- return null;
- } else if (CollectionUtils.isEmpty(def.getImpliedGrants())) {
- return new ArrayList<String>();
- } else {
- List<String> result = new ArrayList<String>(def.getImpliedGrants().size());
- for (String name : def.getImpliedGrants()) {
- if (StringUtils.isBlank(name)) {
- result.add(name); // could be null!
- } else {
- result.add(name.toLowerCase());
- }
- }
- return result;
- }
- }
-
- /**
- * Returns a copy of the policy resource map where all keys (resource-names) are lowercase
- * @param input
- * @return
- */
- Map<String, RangerPolicyResource> getPolicyResourceWithLowerCaseKeys(Map<String, RangerPolicyResource> input) {
- if (input == null) {
- return null;
- }
- Map<String, RangerPolicyResource> output = new HashMap<String, RangerPolicyResource>(input.size());
- for (Map.Entry<String, RangerPolicyResource> entry : input.entrySet()) {
- output.put(entry.getKey().toLowerCase(), entry.getValue());
- }
- return output;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
deleted file mode 100644
index 9ca52f3..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.rest;
-
-import org.apache.ranger.plugin.store.ServiceStore;
-
-public class RangerValidatorFactory {
- public RangerServiceValidator getServiceValidator(ServiceStore store) {
- return new RangerServiceValidator(store);
- }
-
- public RangerPolicyValidator getPolicyValidator(ServiceStore store) {
- return new RangerPolicyValidator(store);
- }
-
- public RangerServiceDefValidator getServiceDefValidator(ServiceStore store) {
- return new RangerServiceDefValidator(store);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
index 85c75f3..470ca50 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
@@ -56,6 +56,11 @@ import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.validation.RangerPolicyValidator;
+import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.RangerServiceValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidatorFactory;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
@@ -67,7 +72,6 @@ import org.apache.ranger.plugin.service.ResourceLookupContext;
import org.apache.ranger.plugin.util.GrantRevokeRequest;
import org.apache.ranger.plugin.util.SearchFilter;
import org.apache.ranger.plugin.util.ServicePolicies;
-import org.apache.ranger.rest.RangerValidator.Action;
import org.apache.ranger.view.VXResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java b/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java
deleted file mode 100644
index 8ceeba1..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.rest;
-
-import java.util.Objects;
-
-public class ValidationFailureDetails {
-
- final String _fieldName;
- final String _subFieldName;
- final boolean _missing;
- final boolean _semanticError;
- final boolean _internalError;
- final String _reason;
-
- public ValidationFailureDetails(String fieldName, String subFieldName, boolean missing, boolean semanticError, boolean internalError, String reason) {
- _missing = missing;
- _semanticError = semanticError;
- _internalError = internalError;
- _fieldName = fieldName;
- _subFieldName = subFieldName;
- _reason = reason;
- }
-
- public String getFieldName() {
- return _fieldName;
- }
-
- public boolean isMissingRequiredValue() {
- return _missing;
- }
-
- public boolean isSemanticallyIncorrect() {
- return _semanticError;
- }
-
- String getType() {
- if (_missing) return "missing";
- if (_semanticError) return "semantically incorrect";
- if (_internalError) return "internal error";
- return "";
- }
-
- public String getSubFieldName() {
- return _subFieldName;
- }
-
- @Override
- public String toString() {
- return String.format("Field[%s]%s is %s: reason[%s]",
- _fieldName,
- _subFieldName == null ? "" : ", subField[" + _subFieldName + "]",
- getType(), _reason);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null || !(obj instanceof ValidationFailureDetails)) {
- return false;
- }
- ValidationFailureDetails that = (ValidationFailureDetails)obj;
- return Objects.equals(_fieldName, that._fieldName) &&
- Objects.equals(_subFieldName, that._subFieldName) &&
- Objects.equals(_reason, that._reason) &&
- _internalError == that._internalError &&
- _missing == that._missing &&
- _semanticError == that._semanticError;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java b/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java
deleted file mode 100644
index b85215d..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.rest;
-
-public class ValidationFailureDetailsBuilder {
- private String _fieldName;
- private boolean _missing;
- private boolean _semanticError;
- private String _reason;
- private String _subFieldName;
- private boolean _internalError;
-
- ValidationFailureDetailsBuilder becauseOf(String aReason) {
- _reason = aReason;
- return this;
- }
-
- ValidationFailureDetailsBuilder isMissing() {
- _missing = true;
- return this;
- }
-
- ValidationFailureDetailsBuilder isSemanticallyIncorrect() {
- _semanticError = true;
- return this;
- }
-
- ValidationFailureDetailsBuilder field(String fieldName) {
- _fieldName = fieldName;
- return this;
- }
-
- ValidationFailureDetails build() {
- return new ValidationFailureDetails(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason);
- }
-
- ValidationFailureDetailsBuilder subField(String missingParameter) {
- _subFieldName = missingParameter;
- return this;
- }
-
- ValidationFailureDetailsBuilder isAnInternalError() {
- _internalError = true;
- return this;
- }
-
-}
[3/4] incubator-ranger git commit: RANGER-278 move validation classes
under org.apache.ranger.plugin.model.validation
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
new file mode 100644
index 0000000..e0f68ad
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
@@ -0,0 +1,524 @@
+package org.apache.ranger.plugin.model.validation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.validation.RangerPolicyValidator;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+
+public class TestRangerPolicyValidator {
+
+ @Before
+ public void setUp() throws Exception {
+ _store = mock(ServiceStore.class);
+ _policy = mock(RangerPolicy.class);
+ _validator = new RangerPolicyValidator(_store);
+ _serviceDef = mock(RangerServiceDef.class);
+ }
+
+ final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
+ final Object[] policyItemsData = new Object[] {
+ ImmutableMap.of( // all good
+ "users", new String[] {"user1" ," user2"},
+ "groups", new String[] {"group1", "group2"},
+ "accesses", new String[] { "r", "w" },
+ "isAllowed", new Boolean[] { true, true }),
+ ImmutableMap.of( // no users, access type different case
+ "groups", new String[] {"group3", "group4"},
+ "accesses", new String[]{"W", "x"},
+ "isAllowed", new Boolean[] { true, true }),
+ ImmutableMap.of( // no groups
+ "users", new String[] {"user3" ," user4"},
+ "accesses", new String[] { "r", "x" },
+ "isAllowed", new Boolean[] { true, true }),
+ ImmutableMap.of( // isallowed on access types is null, case is different from that in definition
+ "users", new String[] {"user7" ," user6"},
+ "accesses", new String[] { "a" },
+ "isAllowed", new Boolean[] { null, null })
+ };
+ String[] accessTypes = new String[] { "r", "w", "x", "A" }; // mix of lower and upper case
+ String[] accessTypes_bad = new String[] { "r", "w", "xx", }; // two missing (x, a), one new that isn't on bad (xx)
+
+ private final Object[][] resourceDefData = new Object[][] {
+ // { name, mandatory, reg-exp, excludesSupported, recursiveSupported }
+ { "db", true, "db\\d+", null, null }, // valid values: db1, db22, db983, etc.; invalid: db, db12x, ttx11, etc.; null => false for excludes and recursive
+ { "tbl", true, null, true, true }, // regex == null => anything goes; excludes == true, recursive == true
+ { "col", false, "col\\d{1,2}", false, true } // valid: col1, col47, etc.; invalid: col, col238, col1, etc., excludes == false, recursive == true
+ };
+
+ private final Object[][] policyResourceMap_good = new Object[][] {
+ // resource-name, values, excludes, recursive
+ { "db", new String[] { "db1", "db2" }, null, null },
+ { "TBL", new String[] { "tbl1", "tbl2" }, true, false } // case should not matter
+ };
+
+ private final Object[][] policyResourceMap_bad = new Object[][] {
+ // resource-name, values, excludes, recursive
+ { "db", new String[] { "db1", "db2" }, null, true }, // mandatory "tbl" missing; recursive==true specified when resource-def does not support it (null)
+ {"col", new String[] { "col12", "col 1" }, true, true }, // wrong format of value for "col"; excludes==true specified when resource-def does not allow it (false)
+ {"extra", new String[] { "extra1", "extra2" }, null, null } // spurious "extra" specified
+ };
+
+ @Test
+ public final void testIsValid_long() throws Exception {
+ // this validation should be removed if we start supporting other than delete action
+ assertFalse(_validator.isValid(3L, Action.CREATE, _failures));
+ _utils.checkFailureForInternalError(_failures);
+
+ // should fail with appropriate error message if id is null
+ _failures.clear(); _failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
+ _utils.checkFailureForMissingValue(_failures, "id");
+
+ // should fail with appropriate error message if policy can't be found for the specified id
+ when(_store.getPolicy(1L)).thenReturn(null);
+ when(_store.getPolicy(2L)).thenThrow(new Exception());
+ RangerPolicy existingPolicy = mock(RangerPolicy.class);
+ when(_store.getPolicy(3L)).thenReturn(existingPolicy);
+ _failures.clear(); assertFalse(_validator.isValid(1L, Action.DELETE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+ _failures.clear(); assertFalse(_validator.isValid(2L, Action.DELETE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+
+ // if policy exists then delete validation should pass
+ assertTrue(_validator.isValid(3L, Action.DELETE, _failures));
+ }
+
+ @Test
+ public final void testIsValid_happyPath() throws Exception {
+ // valid policy has valid non-empty name and service name
+ when(_policy.getService()).thenReturn("service-name");
+ // service name exists
+ RangerService service = mock(RangerService.class);
+ when(service.getType()).thenReturn("service-type");
+ when(_store.getServiceByName("service-name")).thenReturn(service);
+ // service points to a valid service-def
+ _serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes);
+ when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
+ // a matching policy should exist for create when checked by id and not exist when checked by name.
+ when(_store.getPolicy(7L)).thenReturn(null);
+ RangerPolicy existingPolicy = mock(RangerPolicy.class);
+ when(existingPolicy.getId()).thenReturn(8L);
+ when(_store.getPolicy(8L)).thenReturn(existingPolicy);
+ SearchFilter createFilter = new SearchFilter();
+ createFilter.setParam(SearchFilter.POLICY_NAME, "service-type");
+ createFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-1"); // this name would be used for create
+ when(_store.getPolicies(createFilter)).thenReturn(new ArrayList<RangerPolicy>());
+ // a matching policy should not exist for update.
+ SearchFilter updateFilter = new SearchFilter();
+ updateFilter.setParam(SearchFilter.POLICY_NAME, "service-type");
+ updateFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-2"); // this name would be used for update
+ List<RangerPolicy> existingPolicies = new ArrayList<RangerPolicy>();
+ existingPolicies.add(existingPolicy);
+ when(_store.getPolicies(updateFilter)).thenReturn(existingPolicies);
+ // valid policy can have empty set of policy items if audit is turned on
+ // null value for audit is treated as audit on.
+ for (Action action : cu) {
+ for (Boolean auditEnabled : new Boolean[] { null, true } ) {
+ when(_policy.getIsAuditEnabled()).thenReturn(auditEnabled);
+ if (action == Action.CREATE) {
+ when(_policy.getId()).thenReturn(7L);
+ when(_policy.getName()).thenReturn("policy-name-1");
+ assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
+ assertTrue(_failures.isEmpty());
+ } else {
+ // update should work both when by-name is found or not, since nothing found by-name means name is being updated.
+ when(_policy.getId()).thenReturn(8L);
+ when(_policy.getName()).thenReturn("policy-name-1");
+ assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
+ assertTrue(_failures.isEmpty());
+
+ when(_policy.getName()).thenReturn("policy-name-2");
+ assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+ }
+ }
+ // if audit is disabled then policy should have policy items and all of them should be valid
+ List<RangerPolicyItem> policyItems = _utils.createPolicyItems(policyItemsData);
+ when(_policy.getPolicyItems()).thenReturn(policyItems);
+ when(_policy.getIsAuditEnabled()).thenReturn(false);
+ for (Action action : cu) {
+ if (action == Action.CREATE) {
+ when(_policy.getId()).thenReturn(7L);
+ when(_policy.getName()).thenReturn("policy-name-1");
+ } else {
+ when(_policy.getId()).thenReturn(8L);
+ when(_policy.getName()).thenReturn("policy-name-2");
+ }
+ assertTrue("" + action , _validator.isValid(_policy, action, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+
+ // above succeeded as service def did not have any resources on it, mandatory or otherwise.
+ // policy should have all mandatory resources specified, and they should conform to the validation pattern in resource definition
+ List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
+ when(_serviceDef.getResources()).thenReturn(resourceDefs);
+ Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap(policyResourceMap_good);
+ when(_policy.getResources()).thenReturn(resourceMap);
+
+ for (Action action : cu) {
+ if (action == Action.CREATE) {
+ when(_policy.getId()).thenReturn(7L);
+ when(_policy.getName()).thenReturn("policy-name-1");
+ } else {
+ when(_policy.getId()).thenReturn(8L);
+ when(_policy.getName()).thenReturn("policy-name-2");
+ }
+ assertTrue("" + action , _validator.isValid(_policy, action, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+ }
+
+ void checkFailure_isValid(Action action, String errorType, String field) {
+ checkFailure_isValid(action, errorType, field, null);
+ }
+
+ void checkFailure_isValid(Action action, String errorType, String field, String subField) {
+ _failures.clear();
+ assertFalse(_validator.isValid(_policy, action, _failures));
+ switch (errorType) {
+ case "missing":
+ _utils.checkFailureForMissingValue(_failures, field, subField);
+ break;
+ case "semantic":
+ _utils.checkFailureForSemanticError(_failures, field, subField);
+ break;
+ case "internal error":
+ _utils.checkFailureForInternalError(_failures);
+ break;
+ default:
+ fail("Unsupported errorType[" + errorType + "]");
+ break;
+ }
+ }
+
+ @Test
+ public final void testIsValid_failures() throws Exception {
+ for (Action action : cu) {
+ // passing in a null policy should fail with appropriate failure reason
+ _policy = null;
+ checkFailure_isValid(action, "missing", "policy");
+
+ // policy must have a name on it
+ _policy = mock(RangerPolicy.class);
+ for (String name : new String[] { null, " " }) {
+ when(_policy.getName()).thenReturn(name);
+ checkFailure_isValid(action, "missing", "name");
+ }
+
+ // for update id is required!
+ if (action == Action.UPDATE) {
+ when(_policy.getId()).thenReturn(null);
+ checkFailure_isValid(action, "missing", "id");
+ }
+ }
+ /*
+ * Id is ignored for Create but name should not belong to an existing policy. For update, policy should exist for its id and should match its name.
+ */
+ when(_policy.getName()).thenReturn("policy-name");
+ when(_policy.getService()).thenReturn("service-name");
+
+ RangerPolicy existingPolicy = mock(RangerPolicy.class);
+ when(existingPolicy.getId()).thenReturn(7L);
+ List<RangerPolicy> existingPolicies = new ArrayList<RangerPolicy>();
+ existingPolicies.add(existingPolicy);
+ SearchFilter filter = new SearchFilter();
+ filter.setParam(SearchFilter.SERVICE_NAME, "service-name");
+ filter.setParam(SearchFilter.POLICY_NAME, "policy-name");
+ when(_store.getPolicies(filter)).thenReturn(existingPolicies);
+ checkFailure_isValid(Action.CREATE, "semantic", "name");
+
+ // update : does not exist for id
+ when(_policy.getId()).thenReturn(7L);
+ when(_store.getPolicy(7L)).thenReturn(null);
+ checkFailure_isValid(Action.UPDATE, "semantic", "id");
+
+ // Update: name should not point to an existing different policy, i.e. with a different id
+ when(_store.getPolicy(7L)).thenReturn(existingPolicy);
+ RangerPolicy anotherExistingPolicy = mock(RangerPolicy.class);
+ when(anotherExistingPolicy.getId()).thenReturn(8L);
+ existingPolicies.clear();
+ existingPolicies.add(anotherExistingPolicy);
+ when(_store.getPolicies(filter)).thenReturn(existingPolicies);
+ checkFailure_isValid(Action.UPDATE, "semantic", "id/name");
+
+ // more than one policies with same name is also an internal error
+ when(_policy.getName()).thenReturn("policy-name");
+ when(_store.getPolicies(filter)).thenReturn(existingPolicies);
+ existingPolicies.add(existingPolicy);
+ existingPolicy = mock(RangerPolicy.class);
+ existingPolicies.add(existingPolicy);
+ _failures.clear(); assertFalse(_validator.isValid(_policy, Action.UPDATE, _failures));
+ _utils.checkFailureForInternalError(_failures);
+
+ // policy must have service name on it and it should be valid
+ when(_policy.getName()).thenReturn("policy-name");
+ when(_store.getServiceByName("service-name")).thenReturn(null);
+ when(_store.getServiceByName("another-service-name")).thenThrow(new Exception());
+
+ for (Action action : cu) {
+ when(_policy.getService()).thenReturn("service-name");
+ _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "service");
+
+ when(_policy.getService()).thenReturn("another-service-name");
+ _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "service");
+ }
+
+ // policy must contain at least one policy item
+ List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicy.RangerPolicyItem>();
+ when(_policy.getService()).thenReturn("service-name");
+ RangerService service = mock(RangerService.class);
+ when(_store.getServiceByName("service-name")).thenReturn(service);
+ for (Action action : cu) {
+ // when it is null
+ when(_policy.getPolicyItems()).thenReturn(null);
+ _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "policy items");
+ // or when it is not null but empty.
+ when(_policy.getPolicyItems()).thenReturn(policyItems);
+ _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "policy items");
+ }
+
+ // these are known good policy items -- same as used above in happypath
+ policyItems = _utils.createPolicyItems(policyItemsData);
+ when(_policy.getPolicyItems()).thenReturn(policyItems);
+ // policy item check requires that service def should exist
+ when(service.getType()).thenReturn("service-type");
+ when(_store.getServiceDefByName("service-type")).thenReturn(null);
+ for (Action action : cu) {
+ _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+ _utils.checkFailureForInternalError(_failures, "policy service def");
+ }
+
+ // service-def should contain the right access types on it.
+ _serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes_bad);
+ when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
+ for (Action action : cu) {
+ _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+ _utils.checkFailureForSemanticError(_failures, "policy item access type");
+ }
+
+ // create the right service def with right resource defs - this is the same as in the happypath test above.
+ _serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes);
+ when(_store.getPolicies(filter)).thenReturn(null);
+ List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
+ when(_serviceDef.getResources()).thenReturn(resourceDefs);
+ when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
+ // one mandtory is missing (tbl) and one unknown resource is specified (extra), and values of option resource don't conform to validation pattern (col)
+ Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
+ when(_policy.getResources()).thenReturn(policyResources);
+ for (Action action : cu) {
+ _failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "resources", "tbl"); // for missing resource: tbl
+ _utils.checkFailureForSemanticError(_failures, "resources", "extra"); // for spurious resource: "extra"
+ _utils.checkFailureForSemanticError(_failures, "resource-values", "col"); // for spurious resource: "extra"
+ _utils.checkFailureForSemanticError(_failures, "isRecursive", "db"); // for specifying it as true when def did not allow it
+ _utils.checkFailureForSemanticError(_failures, "isExcludes", "col"); // for specifying it as true when def did not allow it
+ }
+ }
+
+ @Test
+ public void test_isValidResourceValues() {
+ List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
+ when(_serviceDef.getResources()).thenReturn(resourceDefs);
+ Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
+ assertFalse(_validator.isValidResourceValues(policyResources, _failures, _serviceDef));
+ _utils.checkFailureForSemanticError(_failures, "resource-values", "col");
+
+ policyResources = _utils.createPolicyResourceMap(policyResourceMap_good);
+ assertTrue(_validator.isValidResourceValues(policyResources, _failures, _serviceDef));
+ }
+
+ @Test
+ public void test_isValidPolicyItems_failures() {
+ // null/empty list is good because there is nothing
+ assertTrue(_validator.isValidPolicyItems(null, _failures, _serviceDef));
+ _failures.isEmpty();
+
+ List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicy.RangerPolicyItem>();
+ assertTrue(_validator.isValidPolicyItems(policyItems, _failures, _serviceDef));
+ _failures.isEmpty();
+
+ // null elements in the list are flagged
+ policyItems.add(null);
+ assertFalse(_validator.isValidPolicyItems(policyItems, _failures, _serviceDef));
+ _utils.checkFailureForMissingValue(_failures, "policy item");
+ }
+
+ @Test
+ public void test_isValidPolicyItem_failures() {
+
+ // empty access collections are invalid
+ RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
+ when(policyItem.getAccesses()).thenReturn(null);
+ _failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
+ _utils.checkFailureForMissingValue(_failures, "policy item accesses");
+
+ List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicy.RangerPolicyItemAccess>();
+ when(policyItem.getAccesses()).thenReturn(accesses);
+ _failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
+ _utils.checkFailureForMissingValue(_failures, "policy item accesses");
+
+ // both user and groups can't be null
+ RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
+ accesses.add(access);
+ when(policyItem.getUsers()).thenReturn(null);
+ when(policyItem.getGroups()).thenReturn(new ArrayList<String>());
+ _failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
+ _utils.checkFailureForMissingValue(_failures, "policy item users/user-groups");
+ }
+
+ @Test
+ public void test_isValidItemAccesses_happyPath() {
+
+ // happy path
+ Object[][] data = new Object[][] {
+ { "a", null }, // valid
+ { "b", true }, // valid
+ { "c", true }, // valid
+ };
+ List<RangerPolicyItemAccess> accesses = _utils.createItemAccess(data);
+ _serviceDef = _utils.createServiceDefWithAccessTypes(new String[] { "a", "b", "c", "d" });
+ assertTrue(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public void test_isValidItemAccesses_failure() {
+
+ // null policy item access values are an error
+ List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicyItemAccess>();
+ accesses.add(null);
+ _failures.clear(); assertFalse(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
+ _utils.checkFailureForMissingValue(_failures, "policy item access");
+
+ // all items must be valid for this call to be valid
+ Object[][] data = new Object[][] {
+ { "a", null }, // valid
+ { null, null }, // invalid - name can't be null
+ { "c", true }, // valid
+ };
+ accesses = _utils.createItemAccess(data);
+ _serviceDef = _utils.createServiceDefWithAccessTypes(new String[] { "a", "b", "c", "d" });
+ _failures.clear(); assertFalse(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
+ }
+
+ @Test
+ public void test_isValidPolicyItemAccess_happyPath() {
+
+ RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
+ when(access.getType()).thenReturn("an-Access"); // valid
+
+ Set<String> validAccesses = Sets.newHashSet(new String[] { "an-access", "another-access" }); // valid accesses should be lower-cased
+
+ // both null or true access types are the same and valid
+ for (Boolean allowed : new Boolean[] { null, true } ) {
+ when(access.getIsAllowed()).thenReturn(allowed);
+ assertTrue(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
+ assertTrue(_failures.isEmpty());
+ }
+ }
+
+ @Test
+ public void test_isValidPolicyItemAccess_failures() {
+
+ Set<String> validAccesses = Sets.newHashSet(new String[] { "anAccess", "anotherAccess" });
+ // null/empty names are invalid
+ RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
+ when(access.getIsAllowed()).thenReturn(null); // valid since null == true
+ for (String type : new String[] { null, " "}) {
+ when(access.getType()).thenReturn(type); // invalid
+ // null/empty validAccess set skips all checks
+ assertTrue(_validator.isValidPolicyItemAccess(access, _failures, null));
+ assertTrue(_validator.isValidPolicyItemAccess(access, _failures, new HashSet<String>()));
+ _failures.clear(); assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
+ _utils.checkFailureForMissingValue(_failures, "policy item access type");
+ }
+
+ when(access.getType()).thenReturn("anAccess"); // valid
+ when(access.getIsAllowed()).thenReturn(false); // invalid
+ _failures.clear();assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
+ _utils.checkFailureForSemanticError(_failures, "policy item access type allowed");
+
+ when(access.getType()).thenReturn("newAccessType"); // invalid
+ _failures.clear(); assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
+ _utils.checkFailureForSemanticError(_failures, "policy item access type");
+ }
+
+ final Object[][] resourceDef_happyPath = new Object[][] {
+ // { "resource-name", "isExcludes", "isRecursive" }
+ { "db", true, true },
+ { "tbl", null, true },
+ { "col", true, false },
+ };
+
+ private Object[][] policyResourceMap_happyPath = new Object[][] {
+ // { "resource-name", "isExcludes", "isRecursive" }
+ { "db", null, true }, // null should be treated as false
+ { "tbl", false, false }, // set to false where def is null and def is true
+ { "col", true, null} // set to null where def is false
+ };
+
+ @Test
+ public final void test_isValidResourceFlags_happyPath() {
+ // passing null values effectively bypasses the filter
+ assertTrue(_validator.isValidResourceFlags(null, _failures, null, "a-service-def", "a-policy"));
+ // so does passing in empty collections
+ Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap2(policyResourceMap_happyPath);
+ List<RangerResourceDef> resourceDefs = _utils.createResourceDefs2(resourceDef_happyPath);
+ when(_serviceDef.getResources()).thenReturn(resourceDefs);
+ assertTrue(_validator.isValidResourceFlags(resourceMap, _failures, resourceDefs, "a-service-def", "a-policy"));
+ }
+
+ private Object[][] policyResourceMap_failures = new Object[][] {
+ // { "resource-name", "isExcludes", "isRecursive" }
+ { "db", true, true }, // ok: def has true for both
+ { "tbl", true, null }, // excludes: def==false, policy==true
+ { "col", false, true } // recursive: def==null (i.e. false), policy==true
+ };
+
+ @Test
+ public final void test_isValidResourceFlags_failures() {
+ // passing true when def says false/null
+ List<RangerResourceDef> resourceDefs = _utils.createResourceDefs2(resourceDef_happyPath);
+ Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap2(policyResourceMap_failures);
+ when(_serviceDef.getResources()).thenReturn(resourceDefs);
+ assertFalse(_validator.isValidResourceFlags(resourceMap, _failures, resourceDefs, "a-service-def", "a-policy"));
+ _utils.checkFailureForSemanticError(_failures, "isExcludes", "tbl");
+ _utils.checkFailureForSemanticError(_failures, "isRecursive", "col");
+ }
+
+ private ValidationTestUtils _utils = new ValidationTestUtils();
+ private List<ValidationFailureDetails> _failures = new ArrayList<ValidationFailureDetails>();
+ private ServiceStore _store;
+ private RangerPolicy _policy;
+ private RangerPolicyValidator _validator;
+ private RangerServiceDef _serviceDef;
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java
new file mode 100644
index 0000000..1019aa1
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java
@@ -0,0 +1,355 @@
+package org.apache.ranger.plugin.model.validation;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+public class TestRangerServiceDefValidator {
+
+ @Before
+ public void setUp() throws Exception {
+ _store = mock(ServiceStore.class);
+ _validator = new RangerServiceDefValidator(_store);
+ _failures = new ArrayList<ValidationFailureDetails>();
+ _serviceDef = mock(RangerServiceDef.class);
+ }
+
+ final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
+
+ final Object[][] accessTypes_good = new Object[][] {
+ { "read", null }, // ok, null implied grants
+ { "write", new String[] { } }, // ok, empty implied grants
+ { "admin", new String[] { "READ", "write" } } // ok, admin access implies read/write, access types are case-insensitive
+ };
+
+ final Map<String, String[]> enums_good = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" }
+ );
+
+ @Test
+ public final void test_isValid_happyPath_create() throws Exception {
+
+ // setup access types with implied access and couple of enums
+ List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_good);
+ when(_serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
+ List<RangerEnumDef> enumDefs = _utils.createEnumDefs(enums_good);
+ when(_serviceDef.getEnums()).thenReturn(enumDefs);
+
+ // create: id is not relevant, name should not conflict
+ when(_serviceDef.getId()).thenReturn(null); // id is not relevant for create
+ when(_serviceDef.getName()).thenReturn("aServiceDef"); // service has a name
+ when(_store.getServiceDefByName("aServiceDef")).thenReturn(null); // no name collision
+ assertTrue(_validator.isValid(_serviceDef, Action.CREATE, _failures));
+ assertTrue(_failures.isEmpty());
+
+ // update: id should match existing service, name should not point to different service def
+ when(_serviceDef.getId()).thenReturn(5L);
+ RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
+ when(_store.getServiceDef(5L)).thenReturn(existingServiceDef);
+ assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ assertTrue(_failures.isEmpty());
+
+ // update: if name points to a service that it's id should be the same
+ RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
+ when(anotherExistingServiceDef.getId()).thenReturn(5L);
+ when(_store.getServiceDefByName("aServiceDef")).thenReturn(anotherExistingServiceDef);
+ assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void testIsValid_Long_failures() throws Exception {
+ Long id = null;
+ // passing in wrong action type
+ boolean result = _validator.isValid((Long)null, Action.CREATE, _failures);
+ assertFalse(result);
+ _utils.checkFailureForInternalError(_failures);
+ // passing in null id is an error
+ _failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
+ _utils.checkFailureForMissingValue(_failures, "id");
+ // a service def with that id should exist, else it is an error
+ id = 3L;
+ when(_store.getServiceDef(id)).thenReturn(null);
+ _failures.clear(); assertFalse(_validator.isValid(id, Action.DELETE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+ // happypath
+ when(_store.getServiceDef(id)).thenReturn(_serviceDef);
+ _failures.clear(); assertTrue(_validator.isValid(id, Action.DELETE, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void testIsValid_failures_name() throws Exception {
+ // null service def and bad service def name
+ for (Action action : cu) {
+ // passing in null service def is an error
+ assertFalse(_validator.isValid((RangerServiceDef)null, action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "service def");
+ // name should be valid
+ for (String name : new String[] { null, "", " " }) {
+ when(_serviceDef.getName()).thenReturn(name);
+ _failures.clear(); assertFalse(_validator.isValid(_serviceDef, action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "name");
+ }
+ }
+ }
+
+ @Test
+ public final void testIsValid_failures_id() throws Exception {
+ // id is required for update
+ when(_serviceDef.getId()).thenReturn(null);
+ assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ _utils.checkFailureForMissingValue(_failures, "id");
+
+ // update: service should exist for the passed in id
+ Long id = 7L;
+ when(_serviceDef.getId()).thenReturn(id);
+ when(_store.getServiceDef(id)).thenReturn(null);
+ assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+
+ when(_store.getServiceDef(id)).thenThrow(new Exception());
+ assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+ }
+
+ @Test
+ public final void testIsValid_failures_nameId_create() throws Exception {
+ // service shouldn't exist with the name
+ RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
+ when(_store.getServiceDefByName("existing-service")).thenReturn(existingServiceDef);
+ when(_serviceDef.getName()).thenReturn("existing-service");
+ _failures.clear(); assertFalse(_validator.isValid(_serviceDef, Action.CREATE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "name");
+ }
+
+ @Test
+ public final void testIsValid_failures_nameId_update() throws Exception {
+
+ // update: if service exists with the same name then it can't point to a different service
+ Long id = 7L;
+ when(_serviceDef.getId()).thenReturn(id);
+ RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
+ when(existingServiceDef.getId()).thenReturn(id);
+ when(_store.getServiceDef(id)).thenReturn(existingServiceDef);
+
+ String name = "aServiceDef";
+ when(_serviceDef.getName()).thenReturn(name);
+ RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
+ Long anotherId = 49L;
+ when(anotherExistingServiceDef.getId()).thenReturn(anotherId);
+ when(_store.getServiceDefByName(name)).thenReturn(anotherExistingServiceDef);
+
+ assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id/name");
+ }
+
+ final Object[][] accessTypes_bad_unknownType = new Object[][] {
+ { "read", null }, // ok, null implied grants
+ { "write", new String[] { } }, // ok, empty implied grants
+ { "admin", new String[] { "ReaD", "execute" } } // non-existent access type (execute), read is good (case should not matter)
+ };
+
+ final Object[][] accessTypes_bad_selfReference = new Object[][] {
+ { "read", null }, // ok, null implied grants
+ { "write", new String[] { } }, // ok, empty implied grants
+ { "admin", new String[] { "write", "admin" } } // non-existent access type (execute)
+ };
+
+ @Test
+ public final void test_isValidAccessTypes_happyPath() {
+ List<RangerAccessTypeDef> input = _utils.createAccessTypeDefs(accessTypes_good);
+ assertTrue(_validator.isValidAccessTypes(input, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void test_isValidAccessTypes_failures() {
+ // sending in empty null access type defs is ok
+ assertTrue(_validator.isValidAccessTypes(null, _failures));
+ assertTrue(_failures.isEmpty());
+
+ List<RangerAccessTypeDef> input = new ArrayList<RangerAccessTypeDef>();
+ _failures.clear(); assertTrue(_validator.isValidAccessTypes(input, _failures));
+ assertTrue(_failures.isEmpty());
+
+ // null/empty access types
+ List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(new String[] { null, "", " " });
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForMissingValue(_failures, "access type name");
+
+ // duplicate access types
+ accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "read" } );
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForSemanticError(_failures, "access type name", "read");
+
+ // duplicate access types - case-insensitive
+ accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "READ" } );
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForSemanticError(_failures, "access type name", "READ");
+
+ // unknown access type in implied grants list
+ accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_unknownType);
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForSemanticError(_failures, "implied grants", "execute");
+
+ // access type with implied grant referring to itself
+ accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_selfReference);
+ _failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+ _utils.checkFailureForSemanticError(_failures, "implied grants", "admin");
+ }
+
+ final Map<String, String[]> enums_bad_enumName_null = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" },
+ "null", new String[] { "foo", "bar", "tar" } // null enum-name -- "null" is a special value that leads to a null enum name
+ );
+
+ final Map<String, String[]> enums_bad_enumName_blank = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" },
+ " ", new String[] { "foo", "bar", "tar" } // enum name is all spaces
+ );
+
+ final Map<String, String[]> enums_bad_Elements_empty = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" },
+ "anEnum", new String[] { } // enum elements collection is empty
+ );
+
+ final Map<String, String[]> enums_bad_enumName_duplicate_exact = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" }
+ );
+
+ final Map<String, String[]> enums_bad_enumName_duplicate_differentCase = ImmutableMap.of(
+ "authentication-type", new String[] { "simple", "kerberos" },
+ "time-unit", new String[] { "day", "hour", "minute" },
+ "Authentication-Type", new String[] { } // duplicate enum-name different in case
+ );
+
+ @Test
+ public final void test_isValidEnums_happyPath() {
+ List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
+ assertTrue(_validator.isValidEnums(input, _failures));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void test_isValidEnums_failures() {
+ // null elements in enum def list are a failure
+ List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
+ input.add(null);
+ assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum def");
+
+ // enum names should be valid
+ input = _utils.createEnumDefs(enums_bad_enumName_null);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum def name");
+
+ input = _utils.createEnumDefs(enums_bad_enumName_blank);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum def name");
+
+ // enum elements collection should not be null or empty
+ input = _utils.createEnumDefs(enums_good);
+ RangerEnumDef anEnumDef = mock(RangerEnumDef.class);
+ when(anEnumDef.getName()).thenReturn("anEnum");
+ when(anEnumDef.getElements()).thenReturn(null);
+ input.add(anEnumDef);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
+
+ input = _utils.createEnumDefs(enums_bad_Elements_empty);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
+
+ // enum names should be distinct -- exact match
+ input = _utils.createEnumDefs(enums_good);
+ // add an element with same name as the first element
+ String name = input.iterator().next().getName();
+ when(anEnumDef.getName()).thenReturn(name);
+ List<RangerEnumElementDef> elementDefs = _utils.createEnumElementDefs(new String[] {"val1", "val2"});
+ when(anEnumDef.getElements()).thenReturn(elementDefs);
+ input.add(anEnumDef);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForSemanticError(_failures, "enum def name", name);
+
+ // enum names should be distinct -- case insensitive
+ input = _utils.createEnumDefs(enums_bad_enumName_duplicate_differentCase);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForSemanticError(_failures, "enum def name", "Authentication-Type");
+
+ // enum default index should be right
+ input = _utils.createEnumDefs(enums_good);
+ // set the index of 1st on to be less than 0
+ when(input.iterator().next().getDefaultIndex()).thenReturn(-1);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
+ // set the index to be more than number of elements
+ when(input.iterator().next().getDefaultIndex()).thenReturn(2);
+ _failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+ _utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
+ }
+
+ @Test
+ public final void test_isValidEnumElements_happyPath() {
+ List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
+ assertTrue(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ assertTrue(_failures.isEmpty());
+ }
+
+ @Test
+ public final void test_isValidEnumElements_failures() {
+ // enum element collection should not have nulls in it
+ List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
+ input.add(null);
+ assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForMissingValue(_failures, "enum element", "anEnum");
+
+ // element names can't be null/empty
+ input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", null });
+ _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
+
+ input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", " " }); // two tabs
+ _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
+
+ // element names should be distinct - case insensitive
+ input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kerberos" }); // duplicate name - exact match
+ _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
+
+ input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kErbErOs" }); // duplicate name - different case
+ _failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+ _utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
+ }
+
+ private ValidationTestUtils _utils = new ValidationTestUtils();
+ RangerServiceDef _serviceDef;
+ List<ValidationFailureDetails> _failures;
+ ServiceStore _store;
+ RangerServiceDefValidator _validator;
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java
new file mode 100644
index 0000000..dd8485e
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java
@@ -0,0 +1,240 @@
+/*
+ * 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.model.validation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.model.validation.RangerServiceValidator;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestRangerServiceValidator {
+
+ final Action[] cud = new Action[] { Action.CREATE, Action.UPDATE, Action.DELETE };
+ final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
+ final Action[] ud = new Action[] { Action.UPDATE, Action.DELETE };
+
+ @Before
+ public void before() {
+ _store = mock(ServiceStore.class);
+ _action = Action.CREATE; // by default we set action to create
+ _validator = new RangerServiceValidator(_store);
+ }
+
+ void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field) {
+ checkFailure_isValid(validator, service, action, failures, errorType, field, null);
+ }
+
+ void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field, String subField) {
+ failures.clear();
+ assertFalse(validator.isValid(service, action, failures));
+ switch (errorType) {
+ case "missing":
+ _utils.checkFailureForMissingValue(failures, field, subField);
+ break;
+ case "semantic":
+ _utils.checkFailureForSemanticError(failures, field, subField);
+ break;
+ case "internal error":
+ _utils.checkFailureForInternalError(failures);
+ break;
+ default:
+ fail("Unsupported errorType[" + errorType + "]");
+ break;
+ }
+ }
+
+ @Test
+ public void testIsValid_failures() throws Exception {
+ RangerService service = mock(RangerService.class);
+ // passing in a null service to the check itself is an error
+ assertFalse(_validator.isValid((RangerService)null, _action, _failures));
+ _utils.checkFailureForMissingValue(_failures, "service");
+
+ // id is required for update
+ when(service.getId()).thenReturn(null);
+ // let's verify the failure and the sort of error information that is returned (for one of these)
+ // assert that among the failure reason is one about id being missing.
+ checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "missing", "id");
+ when(service.getId()).thenReturn(7L);
+
+ for (Action action : cu) {
+ // null, empty of blank name renders a service invalid
+ for (String name : new String[] { null, "", " " }) { // spaces and tabs
+ when(service.getName()).thenReturn(name);
+ checkFailure_isValid(_validator, service, action, _failures, "missing", "name");
+ }
+ // same is true for the type
+ for (String type : new String[] { null, "", " " }) {
+ when(service.getType()).thenReturn(type);
+ checkFailure_isValid(_validator, service, action, _failures, "missing", "type");
+ }
+ }
+ when(service.getName()).thenReturn("aName");
+
+ // if non-empty, then the type should exist!
+ when(_store.getServiceDefByName("null-type")).thenReturn(null);
+ when(_store.getServiceDefByName("throwing-type")).thenThrow(new Exception());
+ for (Action action : cu) {
+ for (String type : new String[] { "null-type", "throwing-type" }) {
+ when(service.getType()).thenReturn(type);
+ checkFailure_isValid(_validator, service, action, _failures, "semantic", "type");
+ }
+ }
+ when(service.getType()).thenReturn("aType");
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
+
+ // Create: No service should exist matching its id and/or name
+ RangerService anExistingService = mock(RangerService.class);
+ when(_store.getServiceByName("aName")).thenReturn(anExistingService);
+ checkFailure_isValid(_validator, service, Action.CREATE, _failures, "semantic", "name");
+
+ // Update: service should exist matching its id and name specified should not belong to a different service
+ when(_store.getService(7L)).thenReturn(null);
+ when(_store.getServiceByName("aName")).thenReturn(anExistingService);
+ checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "semantic", "id");
+
+ when(_store.getService(7L)).thenReturn(anExistingService);
+ RangerService anotherExistingService = mock(RangerService.class);
+ when(anotherExistingService.getId()).thenReturn(49L);
+ when(_store.getServiceByName("aName")).thenReturn(anotherExistingService);
+ checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "semantic", "id/name");
+ }
+
+ @Test
+ public void test_isValid_missingRequiredParameter() throws Exception {
+ // Create/Update: simulate a condition where required parameters are missing
+ Object[][] input = new Object[][] {
+ { "param1", true },
+ { "param2", true },
+ { "param3", false },
+ { "param4", false },
+ };
+ List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(input);
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(serviceDef.getConfigs()).thenReturn(configDefs);
+ // wire this service def into store
+ when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
+ // create a service with some require parameters missing
+ RangerService service = mock(RangerService.class);
+ when(service.getType()).thenReturn("aType");
+ when(service.getName()).thenReturn("aName");
+ // required parameters param2 is missing
+ String[] params = new String[] { "param1", "param3", "param4", "param5" };
+ Map<String, String> paramMap = _utils.createMap(params);
+ when(service.getConfigs()).thenReturn(paramMap);
+ // service does not exist in the store
+ when(_store.getServiceByName("aService")).thenReturn(null);
+ for (Action action : cu) {
+ // it should be invalid
+ checkFailure_isValid(_validator, service, action, _failures, "missing", "configuration", "param2");
+ }
+ }
+
+ @Test
+ public void test_isValid_happyPath() throws Exception {
+ // create a service def with some required parameters
+ Object[][] serviceDefInput = new Object[][] {
+ { "param1", true },
+ { "param2", true },
+ { "param3", false },
+ { "param4", false },
+ { "param5", true },
+ };
+ List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(serviceDefInput);
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(serviceDef.getConfigs()).thenReturn(configDefs);
+ // create a service with some parameters on it
+ RangerService service = mock(RangerService.class);
+ when(service.getName()).thenReturn("aName");
+ when(service.getType()).thenReturn("aType");
+ // contains an extra parameter (param6) and one optional is missing(param4)
+ String[] configs = new String[] { "param1", "param2", "param3", "param5", "param6" };
+ Map<String, String> configMap = _utils.createMap(configs);
+ when(service.getConfigs()).thenReturn(configMap);
+ // wire then into the store
+ // service does not exists
+ when(_store.getServiceByName("aName")).thenReturn(null);
+ // service def exists
+ when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
+
+ assertTrue(_validator.isValid(service, Action.CREATE, _failures));
+
+ // for update to work the only additional requirement is that id is required and service should exist
+ // if name is not null and it points to a service then it should match the id
+ when(service.getId()).thenReturn(7L);
+ RangerService existingService = mock(RangerService.class);
+ when(existingService.getId()).thenReturn(7L);
+ when(_store.getService(7L)).thenReturn(existingService);
+ when(_store.getServiceByName("aName")).thenReturn(existingService);
+ assertTrue(_validator.isValid(service, Action.UPDATE, _failures));
+ // name need not point to a service for update to work, of course.
+ when(_store.getServiceByName("aName")).thenReturn(null);
+ assertTrue(_validator.isValid(service, Action.UPDATE, _failures));
+ }
+
+ @Test
+ public void test_isValid_withId_errorConditions() throws Exception {
+ // api that takes in long is only supported for delete currently
+ assertFalse(_validator.isValid(1L, Action.CREATE, _failures));
+ _utils.checkFailureForInternalError(_failures);
+ // passing in a null id is a failure!
+ _validator = new RangerServiceValidator(_store);
+ _failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
+ _utils.checkFailureForMissingValue(_failures, "id");
+ // if service with that id does not exist then that, too, is a failure
+ when(_store.getService(1L)).thenReturn(null);
+ when(_store.getService(2L)).thenThrow(new Exception());
+ _failures.clear(); assertFalse(_validator.isValid(1L, Action.DELETE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+
+ _failures.clear(); assertFalse(_validator.isValid(2L, Action.DELETE, _failures));
+ _utils.checkFailureForSemanticError(_failures, "id");
+ }
+
+ @Test
+ public void test_isValid_withId_happyPath() throws Exception {
+ _validator = new RangerServiceValidator(_store);
+ RangerService service = mock(RangerService.class);
+ when(_store.getService(1L)).thenReturn(service);
+ assertTrue(_validator.isValid(1L, Action.DELETE, _failures));
+ }
+
+ private ServiceStore _store;
+ private RangerServiceValidator _validator;
+ private Action _action;
+ private ValidationTestUtils _utils = new ValidationTestUtils();
+ private List<ValidationFailureDetails> _failures = new ArrayList<ValidationFailureDetails>();
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
new file mode 100644
index 0000000..f17b2c2
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
@@ -0,0 +1,476 @@
+/*
+ * 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.model.validation;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.model.validation.RangerValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Maps;
+
+public class TestRangerValidator {
+
+ static class RangerValidatorForTest extends RangerValidator {
+
+ public RangerValidatorForTest(ServiceStore store) {
+ super(store);
+ }
+
+ boolean isValid(String behavior) {
+ boolean valid;
+ if (behavior.equals("valid")) {
+ valid = true;
+ } else {
+ valid = false;
+ }
+ return valid;
+ }
+ }
+
+ @Before
+ public void before() {
+ _store = mock(ServiceStore.class);
+ _validator = new RangerValidatorForTest(_store);
+ }
+
+ @Test
+ public void test_ctor_firewalling() {
+ try {
+ // service store can't be null during construction
+ new RangerValidatorForTest(null);
+ fail("Should have thrown exception!");
+ } catch (IllegalArgumentException e) {
+ // expected exception
+ }
+ }
+
+ @Test
+ public void test_validate() {
+ // default implementation should fail. This is abstract class. Sub-class must do something sensible with isValid
+ try {
+ _validator.validate(1L, Action.CREATE);
+ fail("Should have thrown exception!");
+ } catch (Exception e) {
+ // ok expected exception
+ String message = e.getMessage();
+ assertTrue(message.contains("internal error"));
+ }
+ }
+
+ @Test
+ public void test_getServiceConfigParameters() {
+ // reasonable protection against null values
+ Set<String> parameters = _validator.getServiceConfigParameters(null);
+ assertNotNull(parameters);
+ assertTrue(parameters.isEmpty());
+
+ RangerService service = mock(RangerService.class);
+ when(service.getConfigs()).thenReturn(null);
+ parameters = _validator.getServiceConfigParameters(service);
+ assertNotNull(parameters);
+ assertTrue(parameters.isEmpty());
+
+ when(service.getConfigs()).thenReturn(new HashMap<String, String>());
+ parameters = _validator.getServiceConfigParameters(service);
+ assertNotNull(parameters);
+ assertTrue(parameters.isEmpty());
+
+ String[] keys = new String[] { "a", "b", "c" };
+ Map<String, String> map = _utils.createMap(keys);
+ when(service.getConfigs()).thenReturn(map);
+ parameters = _validator.getServiceConfigParameters(service);
+ for (String key: keys) {
+ assertTrue("key", parameters.contains(key));
+ }
+ }
+
+ @Test
+ public void test_getRequiredParameters() {
+ // reasonable protection against null things
+ Set<String> parameters = _validator.getRequiredParameters(null);
+ assertNotNull(parameters);
+ assertTrue(parameters.isEmpty());
+
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(serviceDef.getConfigs()).thenReturn(null);
+ parameters = _validator.getRequiredParameters(null);
+ assertNotNull(parameters);
+ assertTrue(parameters.isEmpty());
+
+ List<RangerServiceConfigDef> configs = new ArrayList<RangerServiceDef.RangerServiceConfigDef>();
+ when(serviceDef.getConfigs()).thenReturn(configs);
+ parameters = _validator.getRequiredParameters(null);
+ assertNotNull(parameters);
+ assertTrue(parameters.isEmpty());
+
+ Object[][] input = new Object[][] {
+ { "param1", false },
+ { "param2", true },
+ { "param3", true },
+ { "param4", false },
+ };
+ configs = _utils.createServiceConditionDefs(input);
+ when(serviceDef.getConfigs()).thenReturn(configs);
+ parameters = _validator.getRequiredParameters(serviceDef);
+ assertTrue("result does not contain: param2", parameters.contains("param2"));
+ assertTrue("result does not contain: param3", parameters.contains("param3"));
+ }
+
+ @Test
+ public void test_getServiceDef() {
+ try {
+ // if service store returns null or throws an exception then service is deemed invalid
+ when(_store.getServiceDefByName("return null")).thenReturn(null);
+ when(_store.getServiceDefByName("throw")).thenThrow(new Exception());
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(_store.getServiceDefByName("good-service")).thenReturn(serviceDef);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Unexpected exception during mocking!");
+ }
+
+ assertNull(_validator.getServiceDef("return null"));
+ assertNull(_validator.getServiceDef("throw"));
+ assertFalse(_validator.getServiceDef("good-service") == null);
+ }
+
+ @Test
+ public void test_getPolicy() throws Exception {
+ // if service store returns null or throws an exception then return null policy
+ when(_store.getPolicy(1L)).thenReturn(null);
+ when(_store.getPolicy(2L)).thenThrow(new Exception());
+ RangerPolicy policy = mock(RangerPolicy.class);
+ when(_store.getPolicy(3L)).thenReturn(policy);
+
+ assertNull(_validator.getPolicy(1L));
+ assertNull(_validator.getPolicy(2L));
+ assertTrue(_validator.getPolicy(3L) != null);
+ }
+
+ @Test
+ public void test_getService_byId() throws Exception {
+ // if service store returns null or throws an exception then service is deemed invalid
+ when(_store.getService(1L)).thenReturn(null);
+ when(_store.getService(2L)).thenThrow(new Exception());
+ RangerService service = mock(RangerService.class);
+ when(_store.getService(3L)).thenReturn(service);
+
+ assertNull(_validator.getService(1L));
+ assertNull(_validator.getService(2L));
+ assertTrue(_validator.getService(3L) != null);
+ }
+
+ @Test
+ public void test_getService() {
+ try {
+ // if service store returns null or throws an exception then service is deemed invalid
+ when(_store.getServiceByName("return null")).thenReturn(null);
+ when(_store.getServiceByName("throw")).thenThrow(new Exception());
+ RangerService service = mock(RangerService.class);
+ when(_store.getServiceByName("good-service")).thenReturn(service);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Unexpected exception during mocking!");
+ }
+
+ assertNull(_validator.getService("return null"));
+ assertNull(_validator.getService("throw"));
+ assertFalse(_validator.getService("good-service") == null);
+ }
+
+ @Test
+ public void test_getAccessTypes() {
+ // passing in null service def
+ Set<String> accessTypes = _validator.getAccessTypes((RangerServiceDef)null);
+ assertTrue(accessTypes.isEmpty());
+ // that has null or empty access type def
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(serviceDef.getAccessTypes()).thenReturn(null);
+ accessTypes = _validator.getAccessTypes(serviceDef);
+ assertTrue(accessTypes.isEmpty());
+
+ List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
+ when(serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
+ accessTypes = _validator.getAccessTypes(serviceDef);
+ assertTrue(accessTypes.isEmpty());
+
+ // having null accesstypedefs
+ accessTypeDefs.add(null);
+ accessTypes = _validator.getAccessTypes(serviceDef);
+ assertTrue(accessTypes.isEmpty());
+
+ // access type defs with null empty blank names are skipped, spaces within names are preserved
+ String[] names = new String[] { null, "", "a", " ", "b ", " ", " C", " D " };
+ accessTypeDefs.addAll(_utils.createAccessTypeDefs(names));
+ accessTypes = _validator.getAccessTypes(serviceDef);
+ assertEquals(4, accessTypes.size());
+ assertTrue(accessTypes.contains("a"));
+ assertTrue(accessTypes.contains("b "));
+ assertTrue(accessTypes.contains(" c"));
+ assertTrue(accessTypes.contains(" d "));
+ }
+
+ @Test
+ public void test_getResourceNames() {
+ // passing in null service def
+ Set<String> accessTypes = _validator.getMandatoryResourceNames((RangerServiceDef)null);
+ assertTrue(accessTypes.isEmpty());
+ // that has null or empty access type def
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(serviceDef.getResources()).thenReturn(null);
+ accessTypes = _validator.getMandatoryResourceNames(serviceDef);
+ assertTrue(accessTypes.isEmpty());
+
+ List<RangerResourceDef> resourceDefs = new ArrayList<RangerResourceDef>();
+ when(serviceDef.getResources()).thenReturn(resourceDefs);
+ accessTypes = _validator.getMandatoryResourceNames(serviceDef);
+ assertTrue(accessTypes.isEmpty());
+
+ // having null accesstypedefs
+ resourceDefs.add(null);
+ accessTypes = _validator.getMandatoryResourceNames(serviceDef);
+ assertTrue(accessTypes.isEmpty());
+
+ // access type defs with null empty blank names are skipped, spaces within names are preserved
+ Object[][] data = {
+ { "a", true }, // all good
+ null, // this should put a null element in the resource def!
+ { "b", null }, // mandatory field is null, i.e. false
+ { "c", false }, // non-mandatory field false - upper case
+ { "D", true }, // resource specified in upper case
+ { "E", false }, // all good
+ };
+ resourceDefs.addAll(_utils.createResourceDefs(data));
+ accessTypes = _validator.getMandatoryResourceNames(serviceDef);
+ assertEquals(2, accessTypes.size());
+ assertTrue(accessTypes.contains("a"));
+ assertTrue(accessTypes.contains("d")); // name should come back lower case
+
+ accessTypes = _validator.getAllResourceNames(serviceDef);
+ assertEquals(5, accessTypes.size());
+ assertTrue(accessTypes.contains("b"));
+ assertTrue(accessTypes.contains("c"));
+ assertTrue(accessTypes.contains("e"));
+ }
+
+ @Test
+ public void test_getValidationRegExes() {
+ // passing in null service def
+ Map<String, String> regExMap = _validator.getValidationRegExes((RangerServiceDef)null);
+ assertTrue(regExMap.isEmpty());
+ // that has null or empty access type def
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(serviceDef.getResources()).thenReturn(null);
+ regExMap = _validator.getValidationRegExes(serviceDef);
+ assertTrue(regExMap.isEmpty());
+
+ List<RangerResourceDef> resourceDefs = new ArrayList<RangerResourceDef>();
+ when(serviceDef.getResources()).thenReturn(resourceDefs);
+ regExMap = _validator.getValidationRegExes(serviceDef);
+ assertTrue(regExMap.isEmpty());
+
+ // having null accesstypedefs
+ resourceDefs.add(null);
+ regExMap = _validator.getValidationRegExes(serviceDef);
+ assertTrue(regExMap.isEmpty());
+
+ // access type defs with null empty blank names are skipped, spaces within names are preserved
+ String[][] data = {
+ { "a", null }, // null-regex
+ null, // this should put a null element in the resource def!
+ { "b", "regex1" }, // valid
+ { "c", "" }, // empty regex
+ { "d", "regex2" }, // valid
+ { "e", " " }, // blank regex
+ { "f", "regex3" }, // all good
+ };
+ resourceDefs.addAll(_utils.createResourceDefsWithRegEx(data));
+ regExMap = _validator.getValidationRegExes(serviceDef);
+ assertEquals(3, regExMap.size());
+ assertEquals("regex1", regExMap.get("b"));
+ assertEquals("regex2", regExMap.get("d"));
+ assertEquals("regex3", regExMap.get("f"));
+ }
+
+ @Test
+ public void test_getPolicyResources() {
+
+ Set<String> result;
+ RangerPolicy policy = null;
+ // null policy
+ result = _validator.getPolicyResources(null);
+ assertTrue(result != null);
+ assertTrue(result.isEmpty());
+ // null resource map
+ policy = mock(RangerPolicy.class);
+ when(policy.getResources()).thenReturn(null);
+ result = _validator.getPolicyResources(null);
+ assertTrue(result != null);
+ assertTrue(result.isEmpty());
+ // empty resource map
+ Map<String, RangerPolicyResource> input = Maps.newHashMap();
+ when(policy.getResources()).thenReturn(input);
+ result = _validator.getPolicyResources(policy);
+ assertTrue(result != null);
+ assertTrue(result.isEmpty());
+ // known resource map
+ input.put("r1", mock(RangerPolicyResource.class));
+ input.put("R2", mock(RangerPolicyResource.class));
+ result = _validator.getPolicyResources(policy);
+ assertEquals(2, result.size());
+ assertTrue("r1", result.contains("r1"));
+ assertTrue("R2", result.contains("r2")); // result should lowercase the resource-names
+ }
+
+ @Test
+ public void test_getIsAuditEnabled() {
+ // null policy
+ RangerPolicy policy = null;
+ boolean result = _validator.getIsAuditEnabled(policy);
+ assertFalse(result);
+ // null isAuditEnabled Boolean is supposed to be TRUE!!
+ policy = mock(RangerPolicy.class);
+ when(policy.getIsAuditEnabled()).thenReturn(null);
+ result = _validator.getIsAuditEnabled(policy);
+ assertTrue(result);
+ // non-null value
+ when(policy.getIsAuditEnabled()).thenReturn(Boolean.FALSE);
+ result = _validator.getIsAuditEnabled(policy);
+ assertFalse(result);
+
+ when(policy.getIsAuditEnabled()).thenReturn(Boolean.TRUE);
+ result = _validator.getIsAuditEnabled(policy);
+ assertTrue(result);
+ }
+
+ @Test
+ public void test_getPolicies() throws Exception {
+
+ // returns null when store returns null
+ String policyName = "aPolicy";
+ String serviceName = "aService";
+ SearchFilter filter = new SearchFilter();
+ filter.setParam(SearchFilter.POLICY_NAME, policyName);
+ filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
+
+ when(_store.getPolicies(filter)).thenReturn(null);
+ List<RangerPolicy> result = _validator.getPolicies(policyName, serviceName);
+ // validate store is queried with both parameters
+ verify(_store).getPolicies(filter);
+ assertNull(result);
+
+ // returns null if store throws an exception
+ when(_store.getPolicies(filter)).thenThrow(new Exception());
+ result = _validator.getPolicies(policyName, serviceName);
+ assertNull(result);
+ }
+
+ @Test
+ public void test_getServiceDef_byId() throws Exception {
+ // if service store returns null or throws an exception then service is deemed invalid
+ when(_store.getServiceDef(1L)).thenReturn(null);
+ when(_store.getServiceDef(2L)).thenThrow(new Exception());
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ when(_store.getServiceDef(3L)).thenReturn(serviceDef);
+
+ assertNull(_validator.getServiceDef(1L));
+ assertNull(_validator.getServiceDef(2L));
+ assertTrue(_validator.getServiceDef(3L) != null);
+ }
+
+ @Test
+ public void test_getEnumDefaultIndex() {
+ RangerEnumDef enumDef = mock(RangerEnumDef.class);
+ assertEquals(-1, _validator.getEnumDefaultIndex(null));
+ when(enumDef.getDefaultIndex()).thenReturn(null);
+ assertEquals(0, _validator.getEnumDefaultIndex(enumDef));
+ when(enumDef.getDefaultIndex()).thenReturn(-5);
+ assertEquals(-5, _validator.getEnumDefaultIndex(enumDef));
+ }
+
+ @Test
+ public void test_getImpliedGrants() {
+
+ // passing in null gets back a null
+ Collection<String> result = _validator.getImpliedGrants(null);
+ assertNull(result);
+
+ // null or empty implied grant collection gets back an empty collection
+ RangerAccessTypeDef accessTypeDef = mock(RangerAccessTypeDef.class);
+ when(accessTypeDef.getImpliedGrants()).thenReturn(null);
+ result = _validator.getImpliedGrants(accessTypeDef);
+ assertTrue(result.isEmpty());
+
+ List<String> impliedGrants = new ArrayList<String>();
+ when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
+ result = _validator.getImpliedGrants(accessTypeDef);
+ assertTrue(result.isEmpty());
+
+ // null/empty values come back as is
+ impliedGrants = Arrays.asList(new String[] { null, "", " ", " " });
+ when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
+ result = _validator.getImpliedGrants(accessTypeDef);
+ assertEquals(4, result.size());
+
+ // non-empty values get lower cased
+ impliedGrants = Arrays.asList(new String[] { "a", "B", "C ", " d " });
+ when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
+ result = _validator.getImpliedGrants(accessTypeDef);
+ assertEquals(4, result.size());
+ assertTrue(result.contains("a"));
+ assertTrue(result.contains("b"));
+ assertTrue(result.contains("c "));
+ assertTrue(result.contains(" d "));
+ }
+
+ private RangerValidatorForTest _validator;
+ private ServiceStore _store;
+ private ValidationTestUtils _utils = new ValidationTestUtils();
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
new file mode 100644
index 0000000..5ed2691
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
@@ -0,0 +1,371 @@
+/*
+ * 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.model.validation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
+
+public class ValidationTestUtils {
+
+ Map<String, String> createMap(String[] keys) {
+ Map<String, String> result = new HashMap<String, String>();
+ for (String key : keys) {
+ result.put(key, "valueof-" + key);
+ }
+ return result;
+ }
+
+ // helper methods for tests
+ List<RangerServiceConfigDef> createServiceConditionDefs(Object[][] input) {
+ List<RangerServiceConfigDef> result = new ArrayList<RangerServiceDef.RangerServiceConfigDef>();
+
+ for (Object data[] : input) {
+ RangerServiceConfigDef aConfigDef = mock(RangerServiceConfigDef.class);
+ when(aConfigDef.getName()).thenReturn((String)data[0]);
+ when(aConfigDef.getMandatory()).thenReturn((boolean)data[1]);
+ result.add(aConfigDef);
+ }
+
+ return result;
+ }
+
+ void checkFailureForSemanticError(List<ValidationFailureDetails> failures, String fieldName) {
+ checkFailure(failures, null, null, true, fieldName, null);
+ }
+
+ void checkFailureForSemanticError(List<ValidationFailureDetails> failures, String fieldName, String subField) {
+ checkFailure(failures, null, null, true, fieldName, subField);
+ }
+
+ void checkFailureForMissingValue(List<ValidationFailureDetails> failures, String field) {
+ checkFailure(failures, null, true, null, field, null);
+ }
+
+ void checkFailureForMissingValue(List<ValidationFailureDetails> failures, String field, String subField) {
+ checkFailure(failures, null, true, null, field, subField);
+ }
+
+ void checkFailureForInternalError(List<ValidationFailureDetails> failures, String fieldName) {
+ checkFailure(failures, true, null, null, fieldName, null);
+ }
+
+ void checkFailureForInternalError(List<ValidationFailureDetails> failures) {
+ checkFailure(failures, true, null, null, null, null);
+ }
+
+ void checkFailure(List<ValidationFailureDetails> failures, Boolean internalError, Boolean missing, Boolean semanticError, String field, String subField) {
+ if (CollectionUtils.isEmpty(failures)) {
+ fail("List of failures is null/empty!");
+ } else {
+ boolean found = false;
+ for (ValidationFailureDetails f : failures) {
+ if ((internalError == null || internalError == f._internalError) &&
+ (missing == null || missing == f._missing) &&
+ (semanticError == null || semanticError == f._semanticError) &&
+ (field == null || field.equals(f._fieldName)) &&
+ (subField == null || subField.equals(f._subFieldName))) {
+ found = true;
+ }
+ }
+ assertTrue(found);
+ }
+ }
+
+ List<RangerAccessTypeDef> createAccessTypeDefs(String[] names) {
+ assertFalse(names == null); // fail if null is passed in!
+ List<RangerAccessTypeDef> defs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
+ for (String name : names) {
+ RangerAccessTypeDef def = mock(RangerAccessTypeDef.class);
+ when(def.getName()).thenReturn(name);
+ defs.add(def);
+ }
+ return defs;
+ }
+
+
+ List<RangerAccessTypeDef> createAccessTypeDefs(Object[][] data) {
+ if (data == null) {
+ return null;
+ }
+ List<RangerAccessTypeDef> result = new ArrayList<RangerAccessTypeDef>();
+ if (data.length == 0) {
+ return result;
+ }
+ for (Object[] entry : data) {
+ String accessType = (String)entry[0];
+ String[] impliedAccessArray = (String[])entry[1];
+ List<String> impliedAccesses = null;
+ if (impliedAccessArray != null) {
+ impliedAccesses = Arrays.asList(impliedAccessArray);
+ }
+ RangerAccessTypeDef aTypeDef = mock(RangerAccessTypeDef.class);
+ when(aTypeDef.getName()).thenReturn(accessType);
+ when(aTypeDef.getImpliedGrants()).thenReturn(impliedAccesses);
+ result.add(aTypeDef);
+ }
+ return result;
+ }
+
+ RangerServiceDef createServiceDefWithAccessTypes(String[] accesses) {
+ RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+ List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
+ for (String access : accesses) {
+ RangerAccessTypeDef accessTypeDef = mock(RangerAccessTypeDef.class);
+ when(accessTypeDef.getName()).thenReturn(access);
+ accessTypeDefs.add(accessTypeDef);
+ }
+ when(serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
+ return serviceDef;
+ }
+
+ List<RangerPolicyItemAccess> createItemAccess(Object[][] data) {
+ List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicyItemAccess>();
+ for (Object[] row : data) {
+ RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
+ when(access.getType()).thenReturn((String)row[0]);
+ when(access.getIsAllowed()).thenReturn((Boolean)row[1]);
+ accesses.add(access);
+ }
+ return accesses;
+ }
+
+ List<RangerPolicyItem> createPolicyItems(Object[] data) {
+ List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicyItem>();
+ for (Object object : data) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object[]> map = (Map<String, Object[]>) object;
+ RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
+
+ List<String> usersList = null;
+ if (map.containsKey("users")) {
+ usersList = Arrays.asList((String[])map.get("users"));
+ }
+ when(policyItem.getUsers()).thenReturn(usersList);
+
+ List<String> groupsList = null;
+ if (map.containsKey("groups")) {
+ groupsList = Arrays.asList((String[])map.get("groups"));
+ }
+ when(policyItem.getGroups()).thenReturn(groupsList);
+
+ String[] accesses = (String[])map.get("accesses");;
+ Boolean[] isAllowedFlags = (Boolean[])map.get("isAllowed");
+ List<RangerPolicyItemAccess> accessesList = null;
+ if (accesses != null && isAllowedFlags != null) {
+ accessesList = new ArrayList<RangerPolicyItemAccess>();
+ for (int i = 0; i < accesses.length; i++) {
+ String access = accesses[i];
+ Boolean isAllowed = isAllowedFlags[i];
+ RangerPolicyItemAccess itemAccess = mock(RangerPolicyItemAccess.class);
+ when(itemAccess.getType()).thenReturn(access);
+ when(itemAccess.getIsAllowed()).thenReturn(isAllowed);
+ accessesList.add(itemAccess);
+ }
+ }
+ when(policyItem.getAccesses()).thenReturn(accessesList);
+
+ policyItems.add(policyItem);
+ }
+ return policyItems;
+ }
+
+ List<RangerResourceDef> createResourceDefs(Object[][] data) {
+ // if data itself is null then return null back
+ if (data == null) {
+ return null;
+ }
+ List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
+ for (Object[] row : data) {
+ RangerResourceDef aDef = null;
+ if (row != null) {
+ String name = null;
+ Boolean mandatory = null;
+ String regExPattern = null;
+ Boolean isExcludesSupported = null;
+ Boolean isRecursiveSupported = null;
+ switch(row.length) {
+ case 5:
+ isRecursiveSupported = (Boolean)row[4];
+ case 4:
+ isExcludesSupported = (Boolean)row[3];
+ case 3:
+ regExPattern = (String)row[2];
+ case 2:
+ mandatory = (Boolean)row[1];
+ case 1:
+ name = (String)row[0];
+ }
+ aDef = mock(RangerResourceDef.class);
+ when(aDef.getName()).thenReturn(name);
+ when(aDef.getMandatory()).thenReturn(mandatory);
+ when(aDef.getValidationRegEx()).thenReturn(regExPattern);
+ when(aDef.getExcludesSupported()).thenReturn(isExcludesSupported);
+ when(aDef.getRecursiveSupported()).thenReturn(isRecursiveSupported);
+ }
+ defs.add(aDef);
+ }
+ return defs;
+ }
+
+ List<RangerResourceDef> createResourceDefs2(Object[][] data) {
+ // if data itself is null then return null back
+ if (data == null) {
+ return null;
+ }
+ List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
+ for (Object[] row : data) {
+ RangerResourceDef aDef = null;
+ if (row != null) {
+ String name = null;
+ Boolean isExcludesSupported = null;
+ Boolean isRecursiveSupported = null;
+ switch(row.length) {
+ case 3:
+ isRecursiveSupported = (Boolean)row[2]; // note: falls through to next case
+ case 2:
+ isExcludesSupported = (Boolean)row[1]; // note: falls through to next case
+ case 1:
+ name = (String)row[0];
+ }
+ aDef = mock(RangerResourceDef.class);
+ when(aDef.getName()).thenReturn(name);
+ when(aDef.getExcludesSupported()).thenReturn(isExcludesSupported);
+ when(aDef.getRecursiveSupported()).thenReturn(isRecursiveSupported);
+ }
+ defs.add(aDef);
+ }
+ return defs;
+ }
+
+ List<RangerResourceDef> createResourceDefsWithRegEx(String[][] data) {
+ // if data itself is null then return null back
+ if (data == null) {
+ return null;
+ }
+ List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
+ for (String[] row : data) {
+ RangerResourceDef aDef = null;
+ if (row != null) {
+ String name = row[0];
+ String regEx = row[1];
+ aDef = mock(RangerResourceDef.class);
+ when(aDef.getName()).thenReturn(name);
+ when(aDef.getValidationRegEx()).thenReturn(regEx);
+ }
+ defs.add(aDef);
+ }
+ return defs;
+ }
+
+ Map<String, RangerPolicyResource> createPolicyResourceMap2(Object[][] input) {
+ if (input == null) {
+ return null;
+ }
+ Map<String, RangerPolicyResource> result = new HashMap<String, RangerPolicyResource>(input.length);
+ for (Object[] row : input) {
+ String resourceName = (String)row[0];
+ Boolean isExcludes = (Boolean)row[1];
+ Boolean isRecursive = (Boolean)row[2];
+ RangerPolicyResource aResource = mock(RangerPolicyResource.class);
+ when(aResource.getIsExcludes()).thenReturn(isExcludes);
+ when(aResource.getIsRecursive()).thenReturn(isRecursive);
+ result.put(resourceName, aResource);
+ }
+ return result;
+ }
+
+ List<RangerEnumElementDef> createEnumElementDefs(String[] input) {
+ if (input == null) {
+ return null;
+ }
+ List<RangerEnumElementDef> output = new ArrayList<RangerEnumElementDef>();
+ for (String elementName : input) {
+ RangerEnumElementDef aDef = mock(RangerEnumElementDef.class);
+ when(aDef.getName()).thenReturn(elementName);
+ output.add(aDef);
+ }
+ return output;
+ }
+
+ List<RangerEnumDef> createEnumDefs(Map<String, String[]> input) {
+ if (input == null) {
+ return null;
+ }
+ List<RangerEnumDef> defs = new ArrayList<RangerEnumDef>();
+ for (Map.Entry<String, String[]> entry : input.entrySet()) {
+ RangerEnumDef enumDef = mock(RangerEnumDef.class);
+ String enumName = entry.getKey();
+ if ("null".equals(enumName)) { // special handling to process null hint in enum-name
+ enumName = null;
+ }
+ when(enumDef.getName()).thenReturn(enumName);
+ List<RangerEnumElementDef> elements = createEnumElementDefs(entry.getValue());
+ when(enumDef.getElements()).thenReturn(elements);
+ // by default set default index to last element
+ when(enumDef.getDefaultIndex()).thenReturn(elements.size() - 1);
+ defs.add(enumDef);
+ }
+ return defs;
+ }
+
+ Map<String, RangerPolicyResource> createPolicyResourceMap(Object[][] input) {
+ if (input == null) {
+ return null;
+ }
+ Map<String, RangerPolicyResource> result = new HashMap<String, RangerPolicyResource>(input.length);
+ for (Object[] row : input) {
+ String resourceName = (String)row[0];
+ String[] valuesArray = (String[])row[1];
+ Boolean isExcludes = (Boolean)row[2];
+ Boolean isRecursive = (Boolean)row[3];
+ RangerPolicyResource aResource = mock(RangerPolicyResource.class);
+ if (valuesArray == null) {
+ when(aResource.getValues()).thenReturn(null);
+ } else {
+ when(aResource.getValues()).thenReturn(Arrays.asList(valuesArray));
+ }
+ when(aResource.getIsExcludes()).thenReturn(isExcludes);
+ when(aResource.getIsRecursive()).thenReturn(isRecursive);
+ result.put(resourceName, aResource);
+ }
+ return result;
+ }
+}
[4/4] incubator-ranger git commit: RANGER-278 move validation classes
under org.apache.ranger.plugin.model.validation
Posted by ma...@apache.org.
RANGER-278 move validation classes under org.apache.ranger.plugin.model.validation
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/7bb68687
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/7bb68687
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/7bb68687
Branch: refs/heads/master
Commit: 7bb686873805b8157644dbd3e9e27632ef8c5590
Parents: 9b35976
Author: Alok Lal <al...@hortonworks.com>
Authored: Sat Mar 14 08:09:54 2015 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Sat Mar 14 11:41:44 2015 -0700
----------------------------------------------------------------------
.../model/validation/RangerPolicyValidator.java | 496 ++++++++++++++++++
.../validation/RangerServiceDefValidator.java | 365 +++++++++++++
.../validation/RangerServiceValidator.java | 207 ++++++++
.../model/validation/RangerValidator.java | 480 +++++++++++++++++
.../validation/RangerValidatorFactory.java | 36 ++
.../validation/ValidationFailureDetails.java | 91 ++++
.../ValidationFailureDetailsBuilder.java | 64 +++
.../validation/TestRangerPolicyValidator.java | 524 +++++++++++++++++++
.../TestRangerServiceDefValidator.java | 355 +++++++++++++
.../validation/TestRangerServiceValidator.java | 240 +++++++++
.../model/validation/TestRangerValidator.java | 476 +++++++++++++++++
.../model/validation/ValidationTestUtils.java | 371 +++++++++++++
.../ranger/rest/RangerPolicyValidator.java | 496 ------------------
.../ranger/rest/RangerServiceDefValidator.java | 365 -------------
.../ranger/rest/RangerServiceValidator.java | 207 --------
.../org/apache/ranger/rest/RangerValidator.java | 480 -----------------
.../ranger/rest/RangerValidatorFactory.java | 36 --
.../org/apache/ranger/rest/ServiceREST.java | 6 +-
.../ranger/rest/ValidationFailureDetails.java | 91 ----
.../rest/ValidationFailureDetailsBuilder.java | 64 ---
.../ranger/rest/TestRangerPolicyValidator.java | 524 -------------------
.../rest/TestRangerServiceDefValidator.java | 355 -------------
.../ranger/rest/TestRangerServiceValidator.java | 240 ---------
.../apache/ranger/rest/TestRangerValidator.java | 476 -----------------
.../rest/TestServiceRESTForValidation.java | 6 +-
.../apache/ranger/rest/ValidationTestUtils.java | 371 -------------
26 files changed, 3715 insertions(+), 3707 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..f5d6bff
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
@@ -0,0 +1,496 @@
+package org.apache.ranger.plugin.model.validation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+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;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerPolicyValidator extends RangerValidator {
+
+ private static final Log LOG = LogFactory.getLog(RangerPolicyValidator.class);
+
+ public RangerPolicyValidator(ServiceStore store) {
+ super(store);
+ }
+
+ public void validate(RangerPolicy policy, Action action) throws Exception {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.validate(%s, %s)", policy, action));
+ }
+
+ List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
+ boolean valid = isValid(policy, action, failures);
+ String message = "";
+ try {
+ if (!valid) {
+ message = serializeFailures(failures);
+ throw new Exception(message);
+ }
+ } finally {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.validate(%s, %s): %s, reason[%s]", policy, action, valid, message));
+ }
+ }
+ }
+
+ @Override
+ boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", id, action, failures));
+ }
+
+ boolean valid = true;
+ if (action != Action.DELETE) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .isAnInternalError()
+ .becauseOf("isValid(Long) is only supported for DELETE")
+ .build());
+ valid = false;
+ } else if (id == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isMissing()
+ .build());
+ valid = false;
+ } else if (getPolicy(id) == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isSemanticallyIncorrect()
+ .becauseOf("no policy found for id[" + id + "]")
+ .build());
+ valid = false;
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", id, action, failures, valid));
+ }
+ return valid;
+ }
+
+ boolean isValid(RangerPolicy policy, Action action, List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policy, action, failures));
+ }
+
+ if (!(action == Action.CREATE || action == Action.UPDATE)) {
+ throw new IllegalArgumentException("isValid(RangerPolicy, ...) is only supported for create/update");
+ }
+ boolean valid = true;
+ if (policy == null) {
+ String message = "policy object passed in was null";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else {
+ Long id = policy.getId();
+ if (action == Action.UPDATE) { // id is ignored for CREATE
+ if (id == null) {
+ String message = "policy id was null/empty/blank";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else if (getPolicy(id) == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isSemanticallyIncorrect()
+ .becauseOf("no policy exists with id[" + id +"]")
+ .build());
+ valid = false;
+ }
+ }
+ String policyName = policy.getName();
+ String serviceName = policy.getService();
+ if (StringUtils.isBlank(policyName)) {
+ String message = "policy name was null/empty/blank[" + policyName + "]";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("name")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else {
+ List<RangerPolicy> policies = getPolicies(policyName, serviceName);
+ if (CollectionUtils.isNotEmpty(policies)) {
+ if (policies.size() > 1) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .isAnInternalError()
+ .becauseOf("multiple policies found with the name[" + policyName + "]")
+ .build());
+ valid = false;
+ } else if (action == Action.CREATE) { // size == 1
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("name")
+ .isSemanticallyIncorrect()
+ .becauseOf("policy already exists with name[" + policyName + "]; its id is[" + policies.iterator().next().getId() + "]")
+ .build());
+ valid = false;
+ } else if (policies.iterator().next().getId() != id) { // size == 1 && action == UPDATE
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id/name")
+ .isSemanticallyIncorrect()
+ .becauseOf("id/name conflict: another policy already exists with name[" + policyName + "], its id is[" + policies.iterator().next().getId() + "]")
+ .build());
+ valid = false;
+ }
+ }
+ }
+ RangerService service = null;
+ if (StringUtils.isBlank(serviceName)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("service")
+ .isMissing()
+ .becauseOf("service name was null/empty/blank")
+ .build());
+ valid = false;
+ } else {
+ service = getService(serviceName);
+ if (service == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("service")
+ .isMissing()
+ .becauseOf("service name was null/empty/blank")
+ .build());
+ valid = false;
+ }
+ }
+ List<RangerPolicyItem> policyItems = policy.getPolicyItems();
+ boolean isAuditEnabled = getIsAuditEnabled(policy);
+ RangerServiceDef serviceDef = null;
+ String serviceDefName = null;
+ if (CollectionUtils.isEmpty(policyItems) && !isAuditEnabled) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy items")
+ .isMissing()
+ .becauseOf("at least one policy item must be specified if audit isn't enabled")
+ .build());
+ valid = false;
+ } else if (service != null) {
+ serviceDefName = service.getType();
+ serviceDef = getServiceDef(serviceDefName);
+ if (serviceDef == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy service def")
+ .isAnInternalError()
+ .becauseOf("Service def of policies service does not exist")
+ .build());
+ valid = false;
+ } else {
+ valid = isValidPolicyItems(policyItems, failures, serviceDef) && valid;
+ }
+ }
+ if (serviceDef != null) {
+ Set<String> mandatoryResources = getMandatoryResourceNames(serviceDef);
+ Set<String> policyResources = getPolicyResources(policy);
+ Set<String> missingResources = Sets.difference(mandatoryResources, policyResources);
+ if (!missingResources.isEmpty()) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("resources")
+ .subField(missingResources.iterator().next()) // we return any one parameter!
+ .isMissing()
+ .becauseOf("required resources[" + missingResources + "] are missing")
+ .build());
+ valid = false;
+ }
+ Set<String> allResource = getAllResourceNames(serviceDef);
+ Set<String> unknownResources = Sets.difference(policyResources, allResource);
+ if (!unknownResources.isEmpty()) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("resources")
+ .subField(unknownResources.iterator().next()) // we return any one parameter!
+ .isSemanticallyIncorrect()
+ .becauseOf("resource[" + unknownResources + "] is not valid for service-def[" + serviceDefName + "]")
+ .build());
+ valid = false;
+ }
+ Map<String, RangerPolicyResource> resourceMap = policy.getResources();
+ valid = isValidResourceValues(resourceMap, failures, serviceDef) && valid;
+ valid = isValidResourceFlags(resourceMap, failures, serviceDef.getResources(), serviceDefName, policyName) && valid;
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policy, action, failures, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidResourceFlags(final Map<String, RangerPolicyResource> inputPolicyResources, final List<ValidationFailureDetails> failures,
+ final List<RangerResourceDef> resourceDefs, final String serviceDefName, final String policyName) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s)", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName));
+ }
+
+ boolean valid = true;
+ if (inputPolicyResources == null) {
+ LOG.debug("isValidResourceFlags: resourceMap is null");
+ } else if (resourceDefs == null) {
+ LOG.debug("isValidResourceFlags: service Def is null");
+ } else {
+ Map<String, RangerPolicyResource> policyResources = getPolicyResourceWithLowerCaseKeys(inputPolicyResources);
+ for (RangerResourceDef resourceDef : resourceDefs) {
+ if (resourceDef == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("resource-def")
+ .isAnInternalError()
+ .becauseOf("a resource-def on resource def collection of service-def[" + serviceDefName + "] was null")
+ .build());
+ valid = false;
+ } else if (StringUtils.isBlank(resourceDef.getName())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("resource-def-name")
+ .isAnInternalError()
+ .becauseOf("name of a resource-def on resource def collection of service-def[" + serviceDefName + "] was null")
+ .build());
+ valid = false;
+ } else {
+ String resourceName = resourceDef.getName().toLowerCase();
+ RangerPolicyResource policyResource = policyResources.get(resourceName);
+ if (policyResource == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("a policy-resource object for resource[" + resourceName + "] on policy [" + policyName + "] was null");
+ }
+ } else {
+ boolean excludesSupported = Boolean.TRUE.equals(resourceDef.getExcludesSupported()); // could be null
+ boolean policyIsExcludes = Boolean.TRUE.equals(policyResource.getIsExcludes()); // could be null
+ if (policyIsExcludes && !excludesSupported) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("isExcludes")
+ .subField(resourceName)
+ .isSemanticallyIncorrect()
+ .becauseOf("isExcludes specified as [" + policyIsExcludes + "] for resource [" + resourceName + "] which doesn't support isExcludes")
+ .build());
+ valid = false;
+ }
+ boolean recursiveSupported = Boolean.TRUE.equals(resourceDef.getRecursiveSupported());
+ boolean policyIsRecursive = Boolean.TRUE.equals(policyResource.getIsRecursive());
+ if (policyIsRecursive && !recursiveSupported) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("isRecursive")
+ .subField(resourceName)
+ .isSemanticallyIncorrect()
+ .becauseOf("isRecursive specified as [" + policyIsRecursive + "] for resource [" + resourceName + "] which doesn't support isRecursive")
+ .build());
+ valid = false;
+ }
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s): %s", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidResourceValues(Map<String, RangerPolicyResource> resourceMap, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.isValidResourceValues(%s, %s, %s)", resourceMap, failures, serviceDef));
+ }
+
+ boolean valid = true;
+ if (resourceMap == null) {
+ LOG.debug("isValidResourceValues: resourceMap is null");
+ } else if (serviceDef == null) {
+ LOG.debug("isValidResourceValues: service Def is null");
+ } else {
+ Map<String, String> validationRegExMap = getValidationRegExes(serviceDef);
+ for (Map.Entry<String, RangerPolicyResource> entry : resourceMap.entrySet()) {
+ String name = entry.getKey();
+ RangerPolicyResource policyResource = entry.getValue();
+ if (validationRegExMap.containsKey(name) && policyResource != null && CollectionUtils.isNotEmpty(policyResource.getValues())) {
+ String regEx = validationRegExMap.get(name);
+ for (String aValue : policyResource.getValues()) {
+ if (StringUtils.isBlank(aValue)) {
+ LOG.debug("resource value was blank");
+ } else if (!aValue.matches(regEx)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("resource-values")
+ .subField(name)
+ .isSemanticallyIncorrect()
+ .becauseOf("resources value[" + aValue + "] does not match validation regex[" + regEx + "] defined on service-def[" + serviceDef.getName() + "]")
+ .build());
+ valid = false;
+ }
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.isValidResourceValues(%s, %s, %s): %s", resourceMap, failures, serviceDef, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidPolicyItems(List<RangerPolicyItem> policyItems, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policyItems, failures, serviceDef));
+ }
+
+ boolean valid = true;
+ if (CollectionUtils.isEmpty(policyItems)) {
+ LOG.debug("policy items collection was null/empty");
+ } else {
+ for (RangerPolicyItem policyItem : policyItems) {
+ if (policyItem == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy item")
+ .isMissing()
+ .becauseOf("policy items object was null")
+ .build());
+ valid = false;
+ } else {
+ // we want to go through all elements even though one may be bad so all failures are captured
+ valid = isValidPolicyItem(policyItem, failures, serviceDef) && valid;
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItems, failures, serviceDef, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidPolicyItem(RangerPolicyItem policyItem, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policyItem, failures, serviceDef));
+ }
+
+ boolean valid = true;
+ if (policyItem == null) {
+ LOG.debug("policy item was null!");
+ } else {
+ // access items collection can't be empty and should be otherwise valid
+ if (CollectionUtils.isEmpty(policyItem.getAccesses())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy item accesses")
+ .isMissing()
+ .becauseOf("policy items accesses collection was null")
+ .build());
+ valid = false;
+ } else {
+ valid = isValidItemAccesses(policyItem.getAccesses(), failures, serviceDef) && valid;
+ }
+ // both users and user-groups collections can't be empty
+ if (CollectionUtils.isEmpty(policyItem.getUsers()) && CollectionUtils.isEmpty(policyItem.getGroups())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy item users/user-groups")
+ .isMissing()
+ .becauseOf("both users and user-groups collections on the policy item were null/empty")
+ .build());
+ valid = false;
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItem, failures, serviceDef, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidItemAccesses(List<RangerPolicyItemAccess> accesses, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", accesses, failures, serviceDef));
+ }
+
+ boolean valid = true;
+ if (CollectionUtils.isEmpty(accesses)) {
+ LOG.debug("policy item accesses collection was null/empty!");
+ } else {
+ Set<String> accessTypes = getAccessTypes(serviceDef);
+ for (RangerPolicyItemAccess access : accesses) {
+ if (access == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy item access")
+ .isMissing()
+ .becauseOf("policy items access object was null")
+ .build());
+ valid = false;
+ } else {
+ // we want to go through all elements even though one may be bad so all failures are captured
+ valid = isValidPolicyItemAccess(access, failures, accessTypes) && valid;
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s): %s", accesses, failures, serviceDef, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidPolicyItemAccess(RangerPolicyItemAccess access, List<ValidationFailureDetails> failures, Set<String> accessTypes) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s)", access, failures, accessTypes));
+ }
+
+ boolean valid = true;
+ if (CollectionUtils.isEmpty(accessTypes)) { // caller should firewall this argument!
+ LOG.debug("isValidPolicyItemAccess: accessTypes was null!");
+ } else if (access == null) {
+ LOG.debug("isValidPolicyItemAccess: policy item access was null!");
+ } else {
+ String accessType = access.getType();
+ if (StringUtils.isBlank(accessType)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy item access type")
+ .isMissing()
+ .becauseOf("policy items access type's name was null/empty/blank")
+ .build());
+ valid = false;
+ } else if (!accessTypes.contains(accessType.toLowerCase())) {
+ String message = String.format("access type[%s] not among valid types for service[%s]", accessType, accessTypes);
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy item access type")
+ .isSemanticallyIncorrect()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ }
+ Boolean isAllowed = access.getIsAllowed();
+ // it can be null (which is treated as allowed) but not false
+ if (isAllowed != null && isAllowed == false) {
+ String message = "access type is set to deny. Currently deny access types are not supported.";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("policy item access type allowed")
+ .isSemanticallyIncorrect()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s): %s", access, failures, accessTypes, valid));
+ }
+ return valid;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
new file mode 100644
index 0000000..a870e28
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
@@ -0,0 +1,365 @@
+package org.apache.ranger.plugin.model.validation;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerServiceDefValidator extends RangerValidator {
+
+ private static final Log LOG = LogFactory.getLog(RangerServiceDefValidator.class);
+
+ public RangerServiceDefValidator(ServiceStore store) {
+ super(store);
+ }
+
+ public void validate(final RangerServiceDef serviceDef, final Action action) throws Exception {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerServiceDefValidator.validate(%s, %s)", serviceDef, action));
+ }
+
+ List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
+ boolean valid = isValid(serviceDef, action, failures);
+ String message = "";
+ try {
+ if (!valid) {
+ message = serializeFailures(failures);
+ throw new Exception(message);
+ }
+ } finally {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerServiceDefValidator.validate(%s, %s): %s, reason[%s]", serviceDef, action, valid, message));
+ }
+ }
+ }
+
+ boolean isValid(final Long id, final Action action, final List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerServiceDefValidator.isValid(" + id + ")");
+ }
+
+ boolean valid = true;
+ if (action != Action.DELETE) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .isAnInternalError()
+ .becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
+ .build());
+ valid = false;
+ } else if (id == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isMissing()
+ .build());
+ valid = false;
+ } else if (getServiceDef(id) == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isSemanticallyIncorrect()
+ .becauseOf("no service def found for id[" + id + "]")
+ .build());
+ valid = false;
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerServiceDefValidator.isValid(" + id + "): " + valid);
+ }
+ return valid;
+ }
+
+ boolean isValid(final RangerServiceDef serviceDef, final Action action, final List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerServiceDefValidator.isValid(" + serviceDef + ")");
+ }
+
+ if (!(action == Action.CREATE || action == Action.UPDATE)) {
+ throw new IllegalArgumentException("isValid(RangerServiceDef, ...) is only supported for CREATE/UPDATE");
+ }
+ boolean valid = true;
+ if (serviceDef == null) {
+ String message = "service def object passed in was null";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("service def")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else {
+ Long id = serviceDef.getId();
+ if (action == Action.UPDATE) { // id is ignored for CREATE
+ if (id == null) {
+ String message = "service def id was null/empty/blank";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else if (getServiceDef(id) == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isSemanticallyIncorrect()
+ .becauseOf("no service def exists with id[" + id +"]")
+ .build());
+ valid = false;
+ }
+ }
+ // validate the service def name
+ String name = serviceDef.getName();
+ boolean nameSpecified = StringUtils.isNotBlank(name);
+ if (!nameSpecified) {
+ String message = "service def name[" + name + "] was null/empty/blank";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("name")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else {
+ RangerServiceDef otherServiceDef = getServiceDef(name);
+ if (otherServiceDef != null && action == Action.CREATE) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("name")
+ .isSemanticallyIncorrect()
+ .becauseOf("service def with the name[" + name + "] already exists")
+ .build());
+ valid = false;
+ } else if (otherServiceDef != null && otherServiceDef.getId() !=null && otherServiceDef.getId() != id) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id/name")
+ .isSemanticallyIncorrect()
+ .becauseOf("id/name conflict: another service def already exists with name[" + name + "], its id is [" + otherServiceDef.getId() + "]")
+ .build());
+ valid = false;
+ }
+ }
+ if (CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("access types")
+ .isMissing()
+ .becauseOf("access types collection was null/empty")
+ .build());
+ valid = false;
+ } else {
+ valid = isValidAccessTypes(serviceDef.getAccessTypes(), failures) && valid;
+ }
+ if (CollectionUtils.isEmpty(serviceDef.getEnums())) {
+ LOG.debug("No enums specified on the service def. Ok!");
+ } else {
+ valid = isValidEnums(serviceDef.getEnums(), failures) && valid;
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerServiceDefValidator.isValid(" + serviceDef + "): " + valid);
+ }
+ return valid;
+ }
+
+ boolean isValidAccessTypes(final List<RangerAccessTypeDef> accessTypeDefs, final List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerServiceDefValidator.isValidAccessTypes(%s, %s)", accessTypeDefs, failures));
+ }
+
+ boolean valid = true;
+ if (CollectionUtils.isEmpty(accessTypeDefs)) {
+ LOG.debug("access type def collection is empty/null");
+ } else {
+ List<RangerAccessTypeDef> defsWithImpliedGrants = new ArrayList<RangerAccessTypeDef>();
+ Set<String> accessNames = new HashSet<String>();
+ for (RangerAccessTypeDef def : accessTypeDefs) {
+ String name = def.getName();
+ // name can't be null/empty/blank
+ if (StringUtils.isBlank(name)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("access type name")
+ .isMissing()
+ .becauseOf("access type name[" + name + "] is null/empty")
+ .build());
+ valid = false;
+ } else if (accessNames.contains(name.toLowerCase())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("access type name")
+ .subField(name)
+ .isSemanticallyIncorrect()
+ .becauseOf("duplicate access type names in access types collection: [" + name + "]")
+ .build());
+ valid = false;
+ } else {
+ accessNames.add(name.toLowerCase()); // we have a new unique access type
+ }
+ if (CollectionUtils.isNotEmpty(def.getImpliedGrants())) {
+ defsWithImpliedGrants.add(def);
+ }
+ }
+ // validate implied grants
+ for (RangerAccessTypeDef def : defsWithImpliedGrants) {
+ Collection<String> impliedGrants = getImpliedGrants(def);
+ Set<String> unknownAccessTypes = Sets.difference(Sets.newHashSet(impliedGrants), accessNames);
+ if (!unknownAccessTypes.isEmpty()) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("implied grants")
+ .subField(unknownAccessTypes.iterator().next()) // we return just on item here. Message has all unknow items
+ .isSemanticallyIncorrect()
+ .becauseOf("implied grant[" + impliedGrants + "] contains an unknown access types[" + unknownAccessTypes + "]")
+ .build());
+ valid = false;
+ }
+ // implied grant should not imply itself!
+ String name = def.getName(); // note: this name could be null/blank/empty!
+ if (impliedGrants.contains(name)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("implied grants")
+ .subField(name)
+ .isSemanticallyIncorrect()
+ .becauseOf("implied grants list [" + impliedGrants + "] for access type[" + name + "] contains itself")
+ .build());
+ valid = false;
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerServiceDefValidator.isValidAccessTypes(%s, %s): %s", accessTypeDefs, failures, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidEnums(List<RangerEnumDef> enumDefs, List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumDefs, failures));
+ }
+
+ boolean valid = true;
+ if (CollectionUtils.isEmpty(enumDefs)) {
+ LOG.debug("enum def collection passed in was null/empty");
+ } else {
+ Set<String> enumNames = new HashSet<String>();
+ for (RangerEnumDef enumDef : enumDefs) {
+ if (enumDef == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum def")
+ .isMissing()
+ .becauseOf("An enum def in enums collection is null")
+ .build());
+ valid = false;
+ } else {
+ // enum-names must non-blank and be unique to a service definition
+ String enumName = enumDef.getName();
+ if (StringUtils.isBlank(enumName)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum def name")
+ .isMissing()
+ .becauseOf("enum name [" + enumName + "] is null/empty")
+ .build());
+ valid = false;
+ } else if (enumNames.contains(enumName.toLowerCase())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum def name")
+ .subField(enumName)
+ .isSemanticallyIncorrect()
+ .becauseOf("dumplicate enum name [" + enumName + "] found")
+ .build());
+ valid = false;
+ } else {
+ enumNames.add(enumName.toLowerCase());
+ }
+ // enum must contain at least one valid value and those values should be non-blank and distinct
+ if (CollectionUtils.isEmpty(enumDef.getElements())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum values")
+ .subField(enumName)
+ .isMissing()
+ .becauseOf("enum [" + enumName + "] does not have any elements")
+ .build());
+ valid = false;
+ } else {
+ valid = isValidEnumElements(enumDef.getElements(), failures, enumName) && valid;
+ // default index should be valid
+ int defaultIndex = getEnumDefaultIndex(enumDef);
+ if (defaultIndex < 0 || defaultIndex >= enumDef.getElements().size()) { // max index is one less than the size of the elements list
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum default index")
+ .subField(enumName)
+ .isSemanticallyIncorrect()
+ .becauseOf("default index[" + defaultIndex + "] for enum [" + enumName + "] is invalid")
+ .build());
+ valid = false;
+ }
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumDefs, failures, valid));
+ }
+ return valid;
+ }
+
+ boolean isValidEnumElements(List<RangerEnumElementDef> enumElementsDefs, List<ValidationFailureDetails> failures, String enumName) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumElementsDefs, failures));
+ }
+
+ boolean valid = true;
+ if (CollectionUtils.isEmpty(enumElementsDefs)) {
+ LOG.debug("Enum elements list passed in was null/empty!");
+ } else {
+ // enum element names should be valid and distinct
+ Set<String> elementNames = new HashSet<String>();
+ for (RangerEnumElementDef elementDef : enumElementsDefs) {
+ if (elementDef == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum element")
+ .subField(enumName)
+ .isMissing()
+ .becauseOf("An enum element in enum element collection of enum [" + enumName + "] is null")
+ .build());
+ valid = false;
+ } else {
+ String elementName = elementDef.getName();
+ if (StringUtils.isBlank(elementName)) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum element name")
+ .subField(enumName)
+ .isMissing()
+ .becauseOf("Name of an element of enum [" + enumName + "] is null/empty[" + elementName + "]")
+ .build());
+ valid = false;
+ } else if (elementNames.contains(elementName.toLowerCase())) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("enum element name")
+ .subField(enumName)
+ .isSemanticallyIncorrect()
+ .becauseOf("dumplicate enum element name [" + elementName + "] found for enum[" + enumName + "]")
+ .build());
+ valid = false;
+ } else {
+ elementNames.add(elementName.toLowerCase());
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumElementsDefs, failures, valid));
+ }
+ return valid;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
new file mode 100644
index 0000000..2019284
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
@@ -0,0 +1,207 @@
+/*
+ * 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.model.validation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerServiceValidator extends RangerValidator {
+
+ private static final Log LOG = LogFactory.getLog(RangerServiceValidator.class);
+
+ public RangerServiceValidator(ServiceStore store) {
+ super(store);
+ }
+
+ public void validate(RangerService service, Action action) throws Exception {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("==> RangerServiceValidator.validate(%s, %s)", service, action));
+ }
+
+ List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
+ boolean valid = isValid(service, action, failures);
+ String message = "";
+ try {
+ if (!valid) {
+ message = serializeFailures(failures);
+ throw new Exception(message);
+ }
+ } finally {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug(String.format("<== RangerServiceValidator.validate(%s, %s): %s, reason[%s]", service, action, valid, message));
+ }
+ }
+ }
+
+ boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerServiceValidator.isValid(" + id + ")");
+ }
+
+ boolean valid = true;
+ if (action != Action.DELETE) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .isAnInternalError()
+ .becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
+ .build());
+ valid = false;
+ } else if (id == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isMissing()
+ .build());
+ valid = false;
+ } else if (getService(id) == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isSemanticallyIncorrect()
+ .becauseOf("no service found for id[" + id + "]")
+ .build());
+ valid = false;
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerServiceValidator.isValid(" + id + "): " + valid);
+ }
+ return valid;
+ }
+
+ boolean isValid(RangerService service, Action action, List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerServiceValidator.isValid(" + service + ")");
+ }
+ if (!(action == Action.CREATE || action == Action.UPDATE)) {
+ throw new IllegalArgumentException("isValid(RangerService, ...) is only supported for CREATE/UPDATE");
+ }
+
+ boolean valid = true;
+ if (service == null) {
+ String message = "service object passed in was null";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("service")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else {
+ Long id = service.getId();
+ if (action == Action.UPDATE) { // id is ignored for CREATE
+ if (id == null) {
+ String message = "service id was null/empty/blank";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else if (getService(id) == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id")
+ .isSemanticallyIncorrect()
+ .becauseOf("no service exists with id[" + id +"]")
+ .build());
+ valid = false;
+ }
+ }
+ String name = service.getName();
+ boolean nameSpecified = StringUtils.isNotBlank(name);
+ RangerServiceDef serviceDef = null;
+ if (!nameSpecified) {
+ String message = "service name[" + name + "] was null/empty/blank";
+ LOG.debug(message);
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("name")
+ .isMissing()
+ .becauseOf(message)
+ .build());
+ valid = false;
+ } else {
+ RangerService otherService = getService(name);
+ if (otherService != null && action == Action.CREATE) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("name")
+ .isSemanticallyIncorrect()
+ .becauseOf("service with the name[" + name + "] already exists")
+ .build());
+ valid = false;
+ } else if (otherService != null && otherService.getId() !=null && otherService.getId() != id) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("id/name")
+ .isSemanticallyIncorrect()
+ .becauseOf("id/name conflict: another service already exists with name[" + name + "], its id is [" + otherService.getId() + "]")
+ .build());
+ valid = false;
+ }
+ }
+ String type = service.getType();
+ boolean typeSpecified = StringUtils.isNotBlank(type);
+ if (!typeSpecified) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("type")
+ .isMissing()
+ .becauseOf("service def [" + type + "] was null/empty/blank")
+ .build());
+ valid = false;
+ } else {
+ serviceDef = getServiceDef(type);
+ if (serviceDef == null) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("type")
+ .isSemanticallyIncorrect()
+ .becauseOf("service def named[" + type + "] not found")
+ .build());
+ valid = false;
+ }
+ }
+ if (nameSpecified && serviceDef != null) {
+ // check if required parameters were specified
+ Set<String> reqiredParameters = getRequiredParameters(serviceDef);
+ Set<String> inputParameters = getServiceConfigParameters(service);
+ Set<String> missingParameters = Sets.difference(reqiredParameters, inputParameters);
+ if (!missingParameters.isEmpty()) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .field("configuration")
+ .subField(missingParameters.iterator().next()) // we return any one parameter!
+ .isMissing()
+ .becauseOf("required configuration parameter is missing; missing parameters: " + missingParameters)
+ .build());
+ valid = false;
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerServiceValidator.isValid(" + service + "): " + valid);
+ }
+ return valid;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
new file mode 100644
index 0000000..7bf744e
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
@@ -0,0 +1,480 @@
+/*
+ * 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.model.validation;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+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;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.SearchFilter;
+
+public abstract class RangerValidator {
+
+ private static final Log LOG = LogFactory.getLog(RangerValidator.class);
+
+ ServiceStore _store;
+
+ public enum Action {
+ CREATE, UPDATE, DELETE;
+ };
+
+ protected RangerValidator(ServiceStore store) {
+ if (store == null) {
+ throw new IllegalArgumentException("ServiceValidator(): store is null!");
+ }
+ _store = store;
+ }
+
+ public void validate(Long id, Action action) throws Exception {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.validate(" + id + ")");
+ }
+
+ List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
+ if (isValid(id, action, failures)) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.validate(" + id + "): valid");
+ }
+ } else {
+ String message = serializeFailures(failures);
+ LOG.debug("<== RangerValidator.validate(" + id + "): invalid, reason[" + message + "]");
+ throw new Exception(message);
+ }
+ }
+
+ /**
+ * This method is expected to be overridden by sub-classes. Default implementation provided to not burden implementers from having to implement methods that they know would never be called.
+ * @param id
+ * @param action
+ * @param failures
+ * @return
+ */
+ boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
+ failures.add(new ValidationFailureDetailsBuilder()
+ .isAnInternalError()
+ .becauseOf("unimplemented method called")
+ .build());
+ return false;
+ }
+
+ String serializeFailures(List<ValidationFailureDetails> failures) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getFailureMessage()");
+ }
+
+ String message = null;
+ if (CollectionUtils.isEmpty(failures)) {
+ LOG.warn("serializeFailures: called while list of failures is null/empty!");
+ } else {
+ StringBuilder builder = new StringBuilder();
+ for (ValidationFailureDetails aFailure : failures) {
+ builder.append(aFailure.toString());
+ builder.append(";");
+ }
+ message = builder.toString();
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.serializeFailures(): " + message);
+ }
+ return message;
+ }
+
+ Set<String> getServiceConfigParameters(RangerService service) {
+ if (service == null || service.getConfigs() == null) {
+ return new HashSet<String>();
+ } else {
+ return service.getConfigs().keySet();
+ }
+ }
+
+ Set<String> getRequiredParameters(RangerServiceDef serviceDef) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getRequiredParameters(" + serviceDef + ")");
+ }
+
+ Set<String> result;
+ if (serviceDef == null) {
+ result = Collections.emptySet();
+ } else {
+ List<RangerServiceConfigDef> configs = serviceDef.getConfigs();
+ if (CollectionUtils.isEmpty(configs)) {
+ result = Collections.emptySet();
+ } else {
+ result = new HashSet<String>(configs.size()); // at worse all of the config items are required!
+ for (RangerServiceConfigDef configDef : configs) {
+ if (configDef.getMandatory()) {
+ result.add(configDef.getName());
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getRequiredParameters(" + serviceDef + "): " + result);
+ }
+ return result;
+ }
+
+ RangerServiceDef getServiceDef(Long id) {
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getServiceDef(" + id + ")");
+ }
+ RangerServiceDef result = null;
+ try {
+ result = _store.getServiceDef(id);
+ } catch (Exception e) {
+ LOG.debug("Encountred exception while retrieving service def from service store!", e);
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getServiceDef(" + id + "): " + result);
+ }
+ return result;
+ }
+
+ RangerServiceDef getServiceDef(String type) {
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getServiceDef(" + type + ")");
+ }
+ RangerServiceDef result = null;
+ try {
+ result = _store.getServiceDefByName(type);
+ } catch (Exception e) {
+ LOG.debug("Encountred exception while retrieving service definition from service store!", e);
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getServiceDef(" + type + "): " + result);
+ }
+ return result;
+ }
+
+ RangerService getService(Long id) {
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getService(" + id + ")");
+ }
+ RangerService result = null;
+ try {
+ result = _store.getService(id);
+ } catch (Exception e) {
+ LOG.debug("Encountred exception while retrieving service from service store!", e);
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getService(" + id + "): " + result);
+ }
+ return result;
+ }
+
+ RangerService getService(String name) {
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getService(" + name + ")");
+ }
+ RangerService result = null;
+ try {
+ result = _store.getServiceByName(name);
+ } catch (Exception e) {
+ LOG.debug("Encountred exception while retrieving service from service store!", e);
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getService(" + name + "): " + result);
+ }
+ return result;
+ }
+
+ RangerPolicy getPolicy(Long id) {
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getPolicy(" + id + ")");
+ }
+ RangerPolicy result = null;
+ try {
+ result = _store.getPolicy(id);
+ } catch (Exception e) {
+ LOG.debug("Encountred exception while retrieving policy from service store!", e);
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getPolicy(" + id + "): " + result);
+ }
+ return result;
+ }
+
+ List<RangerPolicy> getPolicies(final String policyName, final String serviceName) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getPolicies(" + policyName + ", " + serviceName + ")");
+ }
+
+ List<RangerPolicy> policies = null;
+ try {
+ SearchFilter filter = new SearchFilter();
+ filter.setParam(SearchFilter.POLICY_NAME, policyName);
+ filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
+
+ policies = _store.getPolicies(filter);
+ } catch (Exception e) {
+ LOG.debug("Encountred exception while retrieving service from service store!", e);
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getPolicies(" + policyName + ", " + serviceName + "): " + policies);
+ }
+ return policies;
+ }
+
+ Set<String> getAccessTypes(RangerServiceDef serviceDef) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getAccessTypes(" + serviceDef + ")");
+ }
+
+ Set<String> accessTypes = new HashSet<String>();
+ if (serviceDef == null) {
+ LOG.warn("serviceDef passed in was null!");
+ } else if (CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
+ LOG.warn("AccessTypeDef collection on serviceDef was null!");
+ } else {
+ for (RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) {
+ if (accessTypeDef == null) {
+ LOG.warn("Access type def was null!");
+ } else {
+ String accessType = accessTypeDef.getName();
+ if (StringUtils.isBlank(accessType)) {
+ LOG.warn("Access type def name was null/empty/blank!");
+ } else {
+ accessTypes.add(accessType.toLowerCase());
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getAccessTypes(" + serviceDef + "): " + accessTypes);
+ }
+ return accessTypes;
+ }
+
+ /**
+ * This function exists to encapsulates the current behavior of code which treats and unspecified audit preference to mean audit is enabled.
+ * @param policy
+ * @return
+ */
+ boolean getIsAuditEnabled(RangerPolicy policy) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getIsAuditEnabled(" + policy + ")");
+ }
+
+ boolean isEnabled = false;
+ if (policy == null) {
+ LOG.warn("policy was null!");
+ } else if (policy.getIsAuditEnabled() == null) {
+ isEnabled = true;
+ } else {
+ isEnabled = policy.getIsAuditEnabled();
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getIsAuditEnabled(" + policy + "): " + isEnabled);
+ }
+ return isEnabled;
+ }
+
+ /**
+ * Returns names of resource types set to lower-case to allow for case-insensitive comparison.
+ * @param serviceDef
+ * @return
+ */
+ Set<String> getMandatoryResourceNames(RangerServiceDef serviceDef) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getMandatoryResourceNames(" + serviceDef + ")");
+ }
+
+ Set<String> resourceNames = new HashSet<String>();
+ if (serviceDef == null) {
+ LOG.warn("serviceDef passed in was null!");
+ } else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
+ LOG.warn("ResourceDef collection on serviceDef was null!");
+ } else {
+ for (RangerResourceDef resourceTypeDef : serviceDef.getResources()) {
+ if (resourceTypeDef == null) {
+ LOG.warn("resource type def was null!");
+ } else {
+ Boolean mandatory = resourceTypeDef.getMandatory();
+ if (mandatory != null && mandatory == true) {
+ String resourceName = resourceTypeDef.getName();
+ if (StringUtils.isBlank(resourceName)) {
+ LOG.warn("Resource def name was null/empty/blank!");
+ } else {
+ resourceNames.add(resourceName.toLowerCase());
+ }
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getMandatoryResourceNames(" + serviceDef + "): " + resourceNames);
+ }
+ return resourceNames;
+ }
+
+ Set<String> getAllResourceNames(RangerServiceDef serviceDef) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidator.getAllResourceNames(" + serviceDef + ")");
+ }
+
+ Set<String> resourceNames = new HashSet<String>();
+ if (serviceDef == null) {
+ LOG.warn("serviceDef passed in was null!");
+ } else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
+ LOG.warn("ResourceDef collection on serviceDef was null!");
+ } else {
+ for (RangerResourceDef resourceTypeDef : serviceDef.getResources()) {
+ if (resourceTypeDef == null) {
+ LOG.warn("resource type def was null!");
+ } else {
+ String resourceName = resourceTypeDef.getName();
+ if (StringUtils.isBlank(resourceName)) {
+ LOG.warn("Resource def name was null/empty/blank!");
+ } else {
+ resourceNames.add(resourceName.toLowerCase());
+ }
+ }
+ }
+ }
+
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidator.getAllResourceNames(" + serviceDef + "): " + resourceNames);
+ }
+ return resourceNames;
+ }
+
+ /**
+ * Returns the resource-types defined on the policy converted to lowe-case
+ * @param policy
+ * @return
+ */
+ Set<String> getPolicyResources(RangerPolicy policy) {
+ if (policy == null || policy.getResources() == null || policy.getResources().isEmpty()) {
+ return new HashSet<String>();
+ } else {
+ Set<String> result = new HashSet<String>();
+ for (String name : policy.getResources().keySet()) {
+ result.add(name.toLowerCase());
+ }
+ return result;
+ }
+ }
+
+ Map<String, String> getValidationRegExes(RangerServiceDef serviceDef) {
+ if (serviceDef == null || CollectionUtils.isEmpty(serviceDef.getResources())) {
+ return new HashMap<String, String>();
+ } else {
+ Map<String, String> result = new HashMap<String, String>();
+ for (RangerResourceDef resourceDef : serviceDef.getResources()) {
+ if (resourceDef == null) {
+ LOG.warn("A resource def in resource def collection is null");
+ } else {
+ String name = resourceDef.getName();
+ String regEx = resourceDef.getValidationRegEx();
+ if (StringUtils.isBlank(name)) {
+ LOG.warn("resource name is null/empty/blank");
+ } else if (StringUtils.isBlank(regEx)) {
+ LOG.debug("validation regex is null/empty/blank");
+ } else {
+ result.put(name, regEx);
+ }
+ }
+ }
+ return result;
+ }
+ }
+
+ int getEnumDefaultIndex(RangerEnumDef enumDef) {
+ int index;
+ if (enumDef == null) {
+ index = -1;
+ } else if (enumDef.getDefaultIndex() == null) {
+ index = 0;
+ } else {
+ index = enumDef.getDefaultIndex();
+ }
+ return index;
+ }
+
+ Collection<String> getImpliedGrants(RangerAccessTypeDef def) {
+ if (def == null) {
+ return null;
+ } else if (CollectionUtils.isEmpty(def.getImpliedGrants())) {
+ return new ArrayList<String>();
+ } else {
+ List<String> result = new ArrayList<String>(def.getImpliedGrants().size());
+ for (String name : def.getImpliedGrants()) {
+ if (StringUtils.isBlank(name)) {
+ result.add(name); // could be null!
+ } else {
+ result.add(name.toLowerCase());
+ }
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Returns a copy of the policy resource map where all keys (resource-names) are lowercase
+ * @param input
+ * @return
+ */
+ Map<String, RangerPolicyResource> getPolicyResourceWithLowerCaseKeys(Map<String, RangerPolicyResource> input) {
+ if (input == null) {
+ return null;
+ }
+ Map<String, RangerPolicyResource> output = new HashMap<String, RangerPolicyResource>(input.size());
+ for (Map.Entry<String, RangerPolicyResource> entry : input.entrySet()) {
+ output.put(entry.getKey().toLowerCase(), entry.getValue());
+ }
+ return output;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
new file mode 100644
index 0000000..f72e8df
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.model.validation;
+
+import org.apache.ranger.plugin.store.ServiceStore;
+
+public class RangerValidatorFactory {
+ public RangerServiceValidator getServiceValidator(ServiceStore store) {
+ return new RangerServiceValidator(store);
+ }
+
+ public RangerPolicyValidator getPolicyValidator(ServiceStore store) {
+ return new RangerPolicyValidator(store);
+ }
+
+ public RangerServiceDefValidator getServiceDefValidator(ServiceStore store) {
+ return new RangerServiceDefValidator(store);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
new file mode 100644
index 0000000..015203a
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
@@ -0,0 +1,91 @@
+/*
+ * 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.model.validation;
+
+import java.util.Objects;
+
+public class ValidationFailureDetails {
+
+ final String _fieldName;
+ final String _subFieldName;
+ final boolean _missing;
+ final boolean _semanticError;
+ final boolean _internalError;
+ final String _reason;
+
+ public ValidationFailureDetails(String fieldName, String subFieldName, boolean missing, boolean semanticError, boolean internalError, String reason) {
+ _missing = missing;
+ _semanticError = semanticError;
+ _internalError = internalError;
+ _fieldName = fieldName;
+ _subFieldName = subFieldName;
+ _reason = reason;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+
+ public boolean isMissingRequiredValue() {
+ return _missing;
+ }
+
+ public boolean isSemanticallyIncorrect() {
+ return _semanticError;
+ }
+
+ String getType() {
+ if (_missing) return "missing";
+ if (_semanticError) return "semantically incorrect";
+ if (_internalError) return "internal error";
+ return "";
+ }
+
+ public String getSubFieldName() {
+ return _subFieldName;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Field[%s]%s is %s: reason[%s]",
+ _fieldName,
+ _subFieldName == null ? "" : ", subField[" + _subFieldName + "]",
+ getType(), _reason);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof ValidationFailureDetails)) {
+ return false;
+ }
+ ValidationFailureDetails that = (ValidationFailureDetails)obj;
+ return Objects.equals(_fieldName, that._fieldName) &&
+ Objects.equals(_subFieldName, that._subFieldName) &&
+ Objects.equals(_reason, that._reason) &&
+ _internalError == that._internalError &&
+ _missing == that._missing &&
+ _semanticError == that._semanticError;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
new file mode 100644
index 0000000..3a57341
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
@@ -0,0 +1,64 @@
+/*
+ * 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.model.validation;
+
+public class ValidationFailureDetailsBuilder {
+ private String _fieldName;
+ private boolean _missing;
+ private boolean _semanticError;
+ private String _reason;
+ private String _subFieldName;
+ private boolean _internalError;
+
+ ValidationFailureDetailsBuilder becauseOf(String aReason) {
+ _reason = aReason;
+ return this;
+ }
+
+ ValidationFailureDetailsBuilder isMissing() {
+ _missing = true;
+ return this;
+ }
+
+ ValidationFailureDetailsBuilder isSemanticallyIncorrect() {
+ _semanticError = true;
+ return this;
+ }
+
+ ValidationFailureDetailsBuilder field(String fieldName) {
+ _fieldName = fieldName;
+ return this;
+ }
+
+ ValidationFailureDetails build() {
+ return new ValidationFailureDetails(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason);
+ }
+
+ ValidationFailureDetailsBuilder subField(String missingParameter) {
+ _subFieldName = missingParameter;
+ return this;
+ }
+
+ ValidationFailureDetailsBuilder isAnInternalError() {
+ _internalError = true;
+ return this;
+ }
+
+}