/* * 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; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.apache.commons.codec.digest.DigestUtils; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; import org.apache.ranger.plugin.model.RangerPolicyResourceSignature.ResourceSerializer; import org.apache.ranger.plugin.model.RangerPolicyResourceSignature.PolicySerializer; import org.apache.ranger.plugin.model.validation.ValidationTestUtils; import org.junit.Assert; import org.junit.Test; public class TestRangerPolicyResourceSignature { @Test public void test_RangerPolicyResourceView_toString() { // null resource RangerPolicyResource resource = null; ResourceSerializer serializer = new ResourceSerializer(resource); Assert.assertEquals("{}", serializer.toString()); // non-null policy resource with null values/recursive flag resource = createPolicyResource(null, null, null); serializer = new ResourceSerializer(resource); Assert.assertEquals("{values=,excludes=false,recursive=false}", serializer.toString()); // valid values in non-asending order resource = createPolicyResource(new String[]{"b", "a", "d", "c"}, true, false); serializer = new ResourceSerializer(resource); Assert.assertEquals("{values=[a, b, c, d],excludes=false,recursive=true}", serializer.toString()); // recursive flag is false and different variation of values to show lexicographic ordering resource = createPolicyResource(new String[]{"9", "A", "e", "_"}, false, true); serializer = new ResourceSerializer(resource); Assert.assertEquals("{values=[9, A, _, e],excludes=true,recursive=false}", serializer.toString()); } RangerPolicyResource createPolicyResource(String[] values, Boolean recursive, Boolean excludes) { RangerPolicyResource resource = mock(RangerPolicyResource.class); if (values == null) { when(resource.getValues()).thenReturn(null); } else { when(resource.getValues()).thenReturn(Arrays.asList(values)); } when(resource.getIsRecursive()).thenReturn(recursive); when(resource.getIsExcludes()).thenReturn(excludes); return resource; } @Test public void test_isPolicyValidForResourceSignatureComputation() { // null policy is invalid RangerPolicy rangerPolicy = null; PolicySerializer policySerializer = new PolicySerializer(rangerPolicy); Assert.assertFalse("policy==null", policySerializer.isPolicyValidForResourceSignatureComputation()); // null resource map is invalid rangerPolicy = mock(RangerPolicy.class); when(rangerPolicy.getResources()).thenReturn(null); policySerializer = new PolicySerializer(rangerPolicy); Assert.assertFalse("policy.getResources()==null", policySerializer.isPolicyValidForResourceSignatureComputation()); // empty resources map is ok! Map<String, RangerPolicyResource> policyResources = new HashMap<>(); when(rangerPolicy.getResources()).thenReturn(policyResources); policySerializer = new PolicySerializer(rangerPolicy); Assert.assertTrue("policy.getResources().isEmpty()", policySerializer.isPolicyValidForResourceSignatureComputation()); // but having a resource map with null key is not ok! RangerPolicyResource aPolicyResource = mock(RangerPolicyResource.class); policyResources.put(null, aPolicyResource); policySerializer = new PolicySerializer(rangerPolicy); Assert.assertFalse("policy.getResources().contains(null)", policySerializer.isPolicyValidForResourceSignatureComputation()); } @Test public void test_RangerPolicyResourceSignature() { // String rep of a null policy is an empty string! and its hash is sha of empty string! RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null); Assert.assertEquals("", signature.asString()); Assert.assertEquals(DigestUtils.sha256Hex(""), signature.getSignature()); } /* * Format of data expected by the utility function which uses this is: * { "resource-name", "values" "isExcludes", "isRecursive" } */ Object[][] first = new Object[][] { { "table", new String[] { "tbl3", "tbl1", "tbl2"}, true, false}, { "db", new String[] { "db1", "db2"}, false, null}, { "col", new String[] { "col2", "col1", "col3"}, null, true}, }; Object[][] first_recursive_null_or_false = new Object[][] { { "table", new String[] { "tbl3", "tbl1", "tbl2"}, true, null}, // recursive flag is false in first { "db", new String[] { "db1", "db2"}, false, null}, { "col", new String[] { "col2", "col1", "col3"}, null, true}, }; Object[][] first_recursive_flag_different = new Object[][] { { "table", new String[] { "tbl3", "tbl1", "tbl2"}, true, false}, { "db", new String[] { "db1", "db2"}, false, null}, { "col", new String[] { "col2", "col1", "col3"}, null, false}, // recursive flag is true in first }; Object[][] first_excludes_null_or_false = new Object[][] { { "table", new String[] { "tbl3", "tbl1", "tbl2"}, true, false}, { "db", new String[] { "db1", "db2"}, false, null}, // excludes flag is null in first { "col", new String[] { "col2", "col1", "col3"}, false, true}, }; Object[][] first_excludes_flag_different = new Object[][] { { "table", new String[] { "tbl3", "tbl1", "tbl2"}, true, false}, { "db", new String[] { "db1", "db2"}, false, null}, { "col", new String[] { "col2", "col1", "col3"}, true, true}, // excludes flag is false in first }; Object[][] data_second = new Object[][] { { "db", new String[] { "db2", "db1"}, false, null}, { "table", new String[] { "tbl2", "tbl3", "tbl1"}, true, false}, { "col", new String[] { "col1", "col3", "col2"}, null, true}, }; @Test public void test_getResourceSignature_happyPath() { // null policy returns signature of empty resource RangerPolicy policy = null; PolicySerializer serializer = new PolicySerializer(policy); Assert.assertTrue("Null policy", serializer.toString() == ""); policy = mock(RangerPolicy.class); when(policy.getPolicyType()).thenReturn(null); Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(first); when(policy.getResources()).thenReturn(policyResources); serializer = new PolicySerializer(policy); String expectedVersion = "version=1"; String expectedType = "type=0"; String expectedResource = "{" + "col={values=[col1, col2, col3],excludes=false,recursive=true}, " + "db={values=[db1, db2],excludes=false,recursive=false}, " + "table={values=[tbl1, tbl2, tbl3],excludes=true,recursive=false}" + "}"; String serializationFormat = "{%s,%s,resource=%s}"; String expectedFull = String.format(serializationFormat, expectedVersion, expectedType, expectedResource); Assert.assertEquals(expectedFull, serializer.toString()); // order of values should not matter policyResources = _utils.createPolicyResourceMap(data_second); when(policy.getResources()).thenReturn(policyResources); Assert.assertEquals(expectedFull, serializer.toString()); // changing the policy type has expected changes when(policy.getPolicyType()).thenReturn(1); expectedType="type=1"; expectedFull = String.format(serializationFormat, expectedVersion, expectedType, expectedResource); Assert.assertEquals(expectedFull, serializer.toString()); } @Test public void test_nullRecursiveFlagIsSameAsFlase() { // create two policies with resources that differ only in the recursive flag such that flags are null in one and false in another RangerPolicy policy1 = createPolicy(first); RangerPolicy policy2 = createPolicy(first_recursive_null_or_false); RangerPolicyResourceSignature signature1 = new RangerPolicyResourceSignature(policy1); RangerPolicyResourceSignature signature2 = new RangerPolicyResourceSignature(policy2); Assert.assertEquals("Recursive flag: null is same as false", signature1.toString(), signature2.toString()); } @Test public void test_onlyDifferByRecursiveFlag() { // create two policies with resources that differ only in the recursive flag, i.e. null/false in one and true in another RangerPolicy policy1 = createPolicy(first); RangerPolicy policy2 = createPolicy(first_recursive_flag_different); RangerPolicyResourceSignature signature1 = new RangerPolicyResourceSignature(policy1); RangerPolicyResourceSignature signature2 = new RangerPolicyResourceSignature(policy2); Assert.assertFalse("Resources differ only by recursive flag true vs false/null", signature1.toString().equals(signature2.toString())); } @Test public void test_nullExcludesFlagIsSameAsFlase() { // create two policies with resources that differ only in the excludes flag such that flags are null in one and false in another RangerPolicy policy1 = createPolicy(first); RangerPolicy policy2 = createPolicy(first_excludes_null_or_false); RangerPolicyResourceSignature signature1 = new RangerPolicyResourceSignature(policy1); RangerPolicyResourceSignature signature2 = new RangerPolicyResourceSignature(policy2); Assert.assertEquals("Excludes flag: null is same as false", signature1.toString(), signature2.toString()); } @Test public void test_onlyDifferByExcludesFlag() { // create two policies with resources that differ only in the excludes flag, i.e. null/false in one and true in another RangerPolicy policy1 = createPolicy(first); RangerPolicy policy2 = createPolicy(first_excludes_flag_different); RangerPolicyResourceSignature signature1 = new RangerPolicyResourceSignature(policy1); RangerPolicyResourceSignature signature2 = new RangerPolicyResourceSignature(policy2); Assert.assertFalse("Resources differ only by excludes flag true vs false/null", signature1.toString().equals(signature2.toString())); } RangerPolicy createPolicy(Object[][] data) { RangerPolicy policy = mock(RangerPolicy.class); Map<String, RangerPolicyResource> resources = _utils.createPolicyResourceMap(data); when(policy.getResources()).thenReturn(resources); return policy; } @Test public void test_integration() { // setup two policies with resources that are structurally different but semantically the same. RangerPolicy aPolicy = mock(RangerPolicy.class); Map<String, RangerPolicyResource> resources = _utils.createPolicyResourceMap(first); when(aPolicy.getResources()).thenReturn(resources); RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature(aPolicy); RangerPolicy anotherPolicy = mock(RangerPolicy.class); resources = _utils.createPolicyResourceMap(data_second); when(anotherPolicy.getResources()).thenReturn(resources); RangerPolicyResourceSignature anotherSignature = new RangerPolicyResourceSignature(anotherPolicy); Assert.assertTrue(signature.equals(anotherSignature)); Assert.assertTrue(anotherSignature.equals(signature)); } ValidationTestUtils _utils = new ValidationTestUtils(); }