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