http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/java/org/apache/nifi/registry/ranger/TestRangerBasePluginWithPolicies.java ---------------------------------------------------------------------- diff --git a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/java/org/apache/nifi/registry/ranger/TestRangerBasePluginWithPolicies.java b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/java/org/apache/nifi/registry/ranger/TestRangerBasePluginWithPolicies.java new file mode 100644 index 0000000..78c346a --- /dev/null +++ b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/java/org/apache/nifi/registry/ranger/TestRangerBasePluginWithPolicies.java @@ -0,0 +1,544 @@ +/* + * 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.nifi.registry.ranger; + +import org.apache.nifi.registry.security.authorization.AccessPolicy; +import org.apache.nifi.registry.security.authorization.AuthorizerConfigurationContext; +import org.apache.nifi.registry.security.authorization.Group; +import org.apache.nifi.registry.security.authorization.RequestAction; +import org.apache.nifi.registry.security.authorization.User; +import org.apache.nifi.registry.security.authorization.UserAndGroups; +import org.apache.nifi.registry.security.authorization.UserGroupProvider; +import org.apache.nifi.registry.security.authorization.UserGroupProviderInitializationContext; +import org.apache.nifi.registry.security.authorization.exception.AuthorizationAccessException; +import org.apache.nifi.registry.security.exception.SecurityProviderCreationException; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.util.ServicePolicies; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +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; + +public class TestRangerBasePluginWithPolicies { + + @Test + public void testPoliciesWithoutUserGroupProvider() { + final String user1 = "user-1"; + final String group1 = "group-1"; + + final String resourceIdentifier1 = "/resource-1"; + RangerPolicy.RangerPolicyResource resource1 = new RangerPolicy.RangerPolicyResource(resourceIdentifier1); + + final Map<String, RangerPolicy.RangerPolicyResource> policy1Resources = new HashMap<>(); + policy1Resources.put(resourceIdentifier1, resource1); + + final RangerPolicy.RangerPolicyItem policy1Item = new RangerPolicy.RangerPolicyItem(); + policy1Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("READ")).collect(Collectors.toList())); + policy1Item.setUsers(Stream.of(user1).collect(Collectors.toList())); + + final RangerPolicy policy1 = new RangerPolicy(); + policy1.setResources(policy1Resources); + policy1.setPolicyItems(Stream.of(policy1Item).collect(Collectors.toList())); + + final String resourceIdentifier2 = "/resource-2"; + RangerPolicy.RangerPolicyResource resource2 = new RangerPolicy.RangerPolicyResource(resourceIdentifier2); + + final Map<String, RangerPolicy.RangerPolicyResource> policy2Resources = new HashMap<>(); + policy2Resources.put(resourceIdentifier2, resource2); + + final RangerPolicy.RangerPolicyItem policy2Item = new RangerPolicy.RangerPolicyItem(); + policy2Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("READ"), new RangerPolicy.RangerPolicyItemAccess("WRITE")).collect(Collectors.toList())); + policy2Item.setGroups(Stream.of(group1).collect(Collectors.toList())); + + final RangerPolicy policy2 = new RangerPolicy(); + policy2.setResources(policy2Resources); + policy2.setPolicyItems(Stream.of(policy2Item).collect(Collectors.toList())); + + final List<RangerPolicy> policies = new ArrayList<>(); + policies.add(policy1); + policies.add(policy2); + + final RangerServiceDef serviceDef = new RangerServiceDef(); + serviceDef.setName("nifi-registry"); + + final ServicePolicies servicePolicies = new ServicePolicies(); + servicePolicies.setPolicies(policies); + servicePolicies.setServiceDef(serviceDef); + + // set all the policies in the plugin + final RangerBasePluginWithPolicies pluginWithPolicies = new RangerBasePluginWithPolicies("nifi-registry", "nifi-registry"); + pluginWithPolicies.setPolicies(servicePolicies); + + // ensure the two ranger policies converted into 3 nifi-registry access policies + final Set<AccessPolicy> accessPolicies = pluginWithPolicies.getAccessPolicies(); + assertEquals(3, accessPolicies.size()); + + // resource 1 -> read but no write + assertFalse(pluginWithPolicies.doesPolicyExist(resourceIdentifier1, RequestAction.WRITE)); + assertTrue(pluginWithPolicies.doesPolicyExist(resourceIdentifier1, RequestAction.READ)); + + // read + final AccessPolicy readResource1 = pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.READ); + assertNotNull(readResource1); + assertTrue(accessPolicies.contains(readResource1)); + assertTrue(readResource1.equals(pluginWithPolicies.getAccessPolicy(readResource1.getIdentifier()))); + assertEquals(1, readResource1.getUsers().size()); + assertTrue(readResource1.getUsers().contains(new User.Builder().identifierGenerateFromSeed(user1).identity(user1).build().getIdentifier())); + assertTrue(readResource1.getGroups().isEmpty()); + + // but no write + assertNull(pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.WRITE)); + + // resource 2 -> read and write + assertTrue(pluginWithPolicies.doesPolicyExist(resourceIdentifier2, RequestAction.WRITE)); + assertTrue(pluginWithPolicies.doesPolicyExist(resourceIdentifier2, RequestAction.READ)); + + // read + final AccessPolicy readResource2 = pluginWithPolicies.getAccessPolicy(resourceIdentifier2, RequestAction.READ); + assertNotNull(readResource2); + assertTrue(accessPolicies.contains(readResource2)); + assertTrue(readResource2.equals(pluginWithPolicies.getAccessPolicy(readResource2.getIdentifier()))); + assertTrue(readResource2.getUsers().isEmpty()); + assertEquals(1, readResource2.getGroups().size()); + assertTrue(readResource2.getGroups().contains(new Group.Builder().identifierGenerateFromSeed(group1).name(group1).build().getIdentifier())); + + // and write + final AccessPolicy writeResource2 = pluginWithPolicies.getAccessPolicy(resourceIdentifier2, RequestAction.READ); + assertNotNull(writeResource2); + assertTrue(accessPolicies.contains(writeResource2)); + assertTrue(writeResource2.equals(pluginWithPolicies.getAccessPolicy(writeResource2.getIdentifier()))); + assertTrue(writeResource2.getUsers().isEmpty()); + assertEquals(1, writeResource2.getGroups().size()); + assertTrue(writeResource2.getGroups().contains(new Group.Builder().identifierGenerateFromSeed(group1).name(group1).build().getIdentifier())); + + // resource 3 -> no read or write + assertFalse(pluginWithPolicies.doesPolicyExist("resource-3", RequestAction.WRITE)); + assertFalse(pluginWithPolicies.doesPolicyExist("resource-3", RequestAction.READ)); + + // no read or write + assertNull(pluginWithPolicies.getAccessPolicy("resource-3", RequestAction.WRITE)); + assertNull(pluginWithPolicies.getAccessPolicy("resource-3", RequestAction.READ)); + } + + @Test + public void testNoPolicies() { + final RangerBasePluginWithPolicies pluginWithPolicies = new RangerBasePluginWithPolicies("nifi-registry", "nifi-registry"); + + assertFalse(pluginWithPolicies.doesPolicyExist("non-existent-resource", RequestAction.READ)); + assertTrue(pluginWithPolicies.getAccessPolicies().isEmpty()); + assertNull(pluginWithPolicies.getAccessPolicy("non-existent-identifier")); + assertNull(pluginWithPolicies.getAccessPolicy("non-existent-resource", RequestAction.READ)); + } + + @Test + public void testDisabledPolicy() { + final String resourceIdentifier1 = "/resource-1"; + RangerPolicy.RangerPolicyResource resource1 = new RangerPolicy.RangerPolicyResource(resourceIdentifier1); + + final Map<String, RangerPolicy.RangerPolicyResource> policy1Resources = new HashMap<>(); + policy1Resources.put(resourceIdentifier1, resource1); + + final RangerPolicy.RangerPolicyItem policy1Item = new RangerPolicy.RangerPolicyItem(); + policy1Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("READ")).collect(Collectors.toList())); + + final RangerPolicy policy1 = new RangerPolicy(); + policy1.setIsEnabled(false); + policy1.setResources(policy1Resources); + policy1.setPolicyItems(Stream.of(policy1Item).collect(Collectors.toList())); + + final List<RangerPolicy> policies = new ArrayList<>(); + policies.add(policy1); + + final RangerServiceDef serviceDef = new RangerServiceDef(); + serviceDef.setName("nifi-registry"); + + final ServicePolicies servicePolicies = new ServicePolicies(); + servicePolicies.setPolicies(policies); + servicePolicies.setServiceDef(serviceDef); + + // set all the policies in the plugin + final RangerBasePluginWithPolicies pluginWithPolicies = new RangerBasePluginWithPolicies("nifi-registry", "nifi-registry"); + pluginWithPolicies.setPolicies(servicePolicies); + + // ensure the policy was skipped + assertFalse(pluginWithPolicies.doesPolicyExist(resourceIdentifier1, RequestAction.READ)); + assertTrue(pluginWithPolicies.getAccessPolicies().isEmpty()); + assertNull(pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.READ)); + } + + @Test + public void testMissingResourceValue() { + final String resourceIdentifier1 = "/resource-1"; + RangerPolicy.RangerPolicyResource resource1 = new RangerPolicy.RangerPolicyResource(); + + final Map<String, RangerPolicy.RangerPolicyResource> policy1Resources = new HashMap<>(); + policy1Resources.put(resourceIdentifier1, resource1); + + final RangerPolicy.RangerPolicyItem policy1Item = new RangerPolicy.RangerPolicyItem(); + policy1Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("WRITE")).collect(Collectors.toList())); + + final RangerPolicy policy1 = new RangerPolicy(); + policy1.setResources(policy1Resources); + policy1.setPolicyItems(Stream.of(policy1Item).collect(Collectors.toList())); + + final List<RangerPolicy> policies = new ArrayList<>(); + policies.add(policy1); + + final RangerServiceDef serviceDef = new RangerServiceDef(); + serviceDef.setName("nifi-registry"); + + final ServicePolicies servicePolicies = new ServicePolicies(); + servicePolicies.setPolicies(policies); + servicePolicies.setServiceDef(serviceDef); + + // set all the policies in the plugin + final RangerBasePluginWithPolicies pluginWithPolicies = new RangerBasePluginWithPolicies("nifi-registry", "nifi-registry"); + pluginWithPolicies.setPolicies(servicePolicies); + + // ensure the policy was skipped + assertFalse(pluginWithPolicies.doesPolicyExist(resourceIdentifier1, RequestAction.WRITE)); + assertTrue(pluginWithPolicies.getAccessPolicies().isEmpty()); + assertNull(pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.WRITE)); + } + + @Test + public void testWildcardResourceValue() { + final String resourceIdentifier1 = "*"; + RangerPolicy.RangerPolicyResource resource1 = new RangerPolicy.RangerPolicyResource(resourceIdentifier1); + + final Map<String, RangerPolicy.RangerPolicyResource> policy1Resources = new HashMap<>(); + policy1Resources.put(resourceIdentifier1, resource1); + + final RangerPolicy.RangerPolicyItem policy1Item = new RangerPolicy.RangerPolicyItem(); + policy1Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("WRITE")).collect(Collectors.toList())); + + final RangerPolicy policy1 = new RangerPolicy(); + policy1.setResources(policy1Resources); + policy1.setPolicyItems(Stream.of(policy1Item).collect(Collectors.toList())); + + final List<RangerPolicy> policies = new ArrayList<>(); + policies.add(policy1); + + final RangerServiceDef serviceDef = new RangerServiceDef(); + serviceDef.setName("nifi-registry"); + + final ServicePolicies servicePolicies = new ServicePolicies(); + servicePolicies.setPolicies(policies); + servicePolicies.setServiceDef(serviceDef); + + // set all the policies in the plugin + final RangerBasePluginWithPolicies pluginWithPolicies = new RangerBasePluginWithPolicies("nifi-registry", "nifi-registry"); + pluginWithPolicies.setPolicies(servicePolicies); + + // ensure the policy was skipped + assertFalse(pluginWithPolicies.doesPolicyExist(resourceIdentifier1, RequestAction.WRITE)); + assertTrue(pluginWithPolicies.getAccessPolicies().isEmpty()); + assertNull(pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.WRITE)); + } + + @Test + public void testExcludesPolicy() { + final String resourceIdentifier1 = "/resource-1"; + RangerPolicy.RangerPolicyResource resource1 = new RangerPolicy.RangerPolicyResource(resourceIdentifier1); + resource1.setIsExcludes(true); + + final Map<String, RangerPolicy.RangerPolicyResource> policy1Resources = new HashMap<>(); + policy1Resources.put(resourceIdentifier1, resource1); + + final RangerPolicy.RangerPolicyItem policy1Item = new RangerPolicy.RangerPolicyItem(); + policy1Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("WRITE")).collect(Collectors.toList())); + + final RangerPolicy policy1 = new RangerPolicy(); + policy1.setResources(policy1Resources); + policy1.setPolicyItems(Stream.of(policy1Item).collect(Collectors.toList())); + + final List<RangerPolicy> policies = new ArrayList<>(); + policies.add(policy1); + + final RangerServiceDef serviceDef = new RangerServiceDef(); + serviceDef.setName("nifi-registry"); + + final ServicePolicies servicePolicies = new ServicePolicies(); + servicePolicies.setPolicies(policies); + servicePolicies.setServiceDef(serviceDef); + + // set all the policies in the plugin + final RangerBasePluginWithPolicies pluginWithPolicies = new RangerBasePluginWithPolicies("nifi-registry", "nifi-registry"); + pluginWithPolicies.setPolicies(servicePolicies); + + // ensure the policy was skipped + assertFalse(pluginWithPolicies.doesPolicyExist(resourceIdentifier1, RequestAction.WRITE)); + assertTrue(pluginWithPolicies.getAccessPolicies().isEmpty()); + assertNull(pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.WRITE)); + } + + @Test + public void testRecursivePolicy() { + final String resourceIdentifier1 = "/resource-1"; + RangerPolicy.RangerPolicyResource resource1 = new RangerPolicy.RangerPolicyResource(resourceIdentifier1); + resource1.setIsRecursive(true); + + final Map<String, RangerPolicy.RangerPolicyResource> policy1Resources = new HashMap<>(); + policy1Resources.put(resourceIdentifier1, resource1); + + final RangerPolicy.RangerPolicyItem policy1Item = new RangerPolicy.RangerPolicyItem(); + policy1Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("WRITE")).collect(Collectors.toList())); + + final RangerPolicy policy1 = new RangerPolicy(); + policy1.setResources(policy1Resources); + policy1.setPolicyItems(Stream.of(policy1Item).collect(Collectors.toList())); + + final List<RangerPolicy> policies = new ArrayList<>(); + policies.add(policy1); + + final RangerServiceDef serviceDef = new RangerServiceDef(); + serviceDef.setName("nifi-registry"); + + final ServicePolicies servicePolicies = new ServicePolicies(); + servicePolicies.setPolicies(policies); + servicePolicies.setServiceDef(serviceDef); + + // set all the policies in the plugin + final RangerBasePluginWithPolicies pluginWithPolicies = new RangerBasePluginWithPolicies("nifi-registry", "nifi-registry"); + pluginWithPolicies.setPolicies(servicePolicies); + + // ensure the policy was skipped + assertFalse(pluginWithPolicies.doesPolicyExist(resourceIdentifier1, RequestAction.WRITE)); + assertTrue(pluginWithPolicies.getAccessPolicies().isEmpty()); + assertNull(pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.WRITE)); + } + + @Test + public void testDelegateAdmin() { + final String user1 = "user-1"; + + final String resourceIdentifier1 = "/resource-1"; + RangerPolicy.RangerPolicyResource resource1 = new RangerPolicy.RangerPolicyResource(resourceIdentifier1); + + final Map<String, RangerPolicy.RangerPolicyResource> policy1Resources = new HashMap<>(); + policy1Resources.put(resourceIdentifier1, resource1); + + final RangerPolicy.RangerPolicyItem policy1Item = new RangerPolicy.RangerPolicyItem(); + policy1Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("READ"), new RangerPolicy.RangerPolicyItemAccess("WRITE")).collect(Collectors.toList())); + policy1Item.setUsers(Stream.of(user1).collect(Collectors.toList())); + policy1Item.setDelegateAdmin(true); + + final RangerPolicy policy1 = new RangerPolicy(); + policy1.setResources(policy1Resources); + policy1.setPolicyItems(Stream.of(policy1Item).collect(Collectors.toList())); + + final List<RangerPolicy> policies = new ArrayList<>(); + policies.add(policy1); + + final RangerServiceDef serviceDef = new RangerServiceDef(); + serviceDef.setName("nifi-registry"); + + final ServicePolicies servicePolicies = new ServicePolicies(); + servicePolicies.setPolicies(policies); + servicePolicies.setServiceDef(serviceDef); + + // set all the policies in the plugin + final RangerBasePluginWithPolicies pluginWithPolicies = new RangerBasePluginWithPolicies("nifi-registry", "nifi-registry"); + pluginWithPolicies.setPolicies(servicePolicies); + + assertEquals(4, pluginWithPolicies.getAccessPolicies().size()); + assertNotNull(pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.READ)); + assertNotNull(pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.WRITE)); + assertNotNull(pluginWithPolicies.getAccessPolicy("/policies" + resourceIdentifier1, RequestAction.READ)); + assertNotNull(pluginWithPolicies.getAccessPolicy("/policies" + resourceIdentifier1, RequestAction.WRITE)); + } + + @Test + public void testPoliciesWithUserGroupProvider() { + final String user1 = "user-1"; // unknown according to user group provider + final String user2 = "user-2"; // known according to user group provider + final String group1 = "group-1"; // unknown according to user group provider + final String group2 = "group-2"; // known according to user group provider + + final UserGroupProvider userGroupProvider = new UserGroupProvider() { + @Override + public Set<User> getUsers() throws AuthorizationAccessException { + return Stream.of(new User.Builder().identifierGenerateFromSeed(user2).identity(user2).build()).collect(Collectors.toSet()); + } + + @Override + public User getUser(String identifier) throws AuthorizationAccessException { + final User u2 = new User.Builder().identifierGenerateFromSeed(user2).identity(user2).build(); + if (u2.getIdentifier().equals(identifier)) { + return u2; + } else { + return null; + } + } + + @Override + public User getUserByIdentity(String identity) throws AuthorizationAccessException { + if (user2.equals(identity)) { + return new User.Builder().identifierGenerateFromSeed(user2).identity(user2).build(); + } else { + return null; + } + } + + @Override + public Set<Group> getGroups() throws AuthorizationAccessException { + return Stream.of(new Group.Builder().identifierGenerateFromSeed(group2).name(group2).build()).collect(Collectors.toSet()); + } + + @Override + public Group getGroup(String identifier) throws AuthorizationAccessException { + final Group g2 = new Group.Builder().identifierGenerateFromSeed(group2).name(group2).build(); + if (g2.getIdentifier().equals(identifier)) { + return g2; + } else { + return null; + } + } + + @Override + public UserAndGroups getUserAndGroups(String identity) throws AuthorizationAccessException { + if (user2.equals(identity)) { + return new UserAndGroups() { + @Override + public User getUser() { + return new User.Builder().identifierGenerateFromSeed(user2).identity(user2).build(); + } + + @Override + public Set<Group> getGroups() { + return Collections.EMPTY_SET; + } + }; + } else { + return null; + } + } + + @Override + public void initialize(UserGroupProviderInitializationContext initializationContext) throws SecurityProviderCreationException { + } + + @Override + public void onConfigured(AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException { + } + + @Override + public void preDestruction() throws SecurityProviderCreationException { + } + }; + + final String resourceIdentifier1 = "/resource-1"; + RangerPolicy.RangerPolicyResource resource1 = new RangerPolicy.RangerPolicyResource(resourceIdentifier1); + + final Map<String, RangerPolicy.RangerPolicyResource> policy1Resources = new HashMap<>(); + policy1Resources.put(resourceIdentifier1, resource1); + + final RangerPolicy.RangerPolicyItem policy1Item = new RangerPolicy.RangerPolicyItem(); + policy1Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("READ")).collect(Collectors.toList())); + policy1Item.setUsers(Stream.of(user1).collect(Collectors.toList())); + policy1Item.setGroups(Stream.of(group2).collect(Collectors.toList())); + + final RangerPolicy policy1 = new RangerPolicy(); + policy1.setResources(policy1Resources); + policy1.setPolicyItems(Stream.of(policy1Item).collect(Collectors.toList())); + + final String resourceIdentifier2 = "/resource-2"; + RangerPolicy.RangerPolicyResource resource2 = new RangerPolicy.RangerPolicyResource(resourceIdentifier2); + + final Map<String, RangerPolicy.RangerPolicyResource> policy2Resources = new HashMap<>(); + policy2Resources.put(resourceIdentifier2, resource2); + + final RangerPolicy.RangerPolicyItem policy2Item = new RangerPolicy.RangerPolicyItem(); + policy2Item.setAccesses(Stream.of(new RangerPolicy.RangerPolicyItemAccess("READ"), new RangerPolicy.RangerPolicyItemAccess("WRITE")).collect(Collectors.toList())); + policy2Item.setUsers(Stream.of(user2).collect(Collectors.toList())); + policy2Item.setGroups(Stream.of(group1).collect(Collectors.toList())); + + final RangerPolicy policy2 = new RangerPolicy(); + policy2.setResources(policy2Resources); + policy2.setPolicyItems(Stream.of(policy2Item).collect(Collectors.toList())); + + final List<RangerPolicy> policies = new ArrayList<>(); + policies.add(policy1); + policies.add(policy2); + + final RangerServiceDef serviceDef = new RangerServiceDef(); + serviceDef.setName("nifi-registry"); + + final ServicePolicies servicePolicies = new ServicePolicies(); + servicePolicies.setPolicies(policies); + servicePolicies.setServiceDef(serviceDef); + + // set all the policies in the plugin + final RangerBasePluginWithPolicies pluginWithPolicies = new RangerBasePluginWithPolicies("nifi-registry", "nifi-registry", userGroupProvider); + pluginWithPolicies.setPolicies(servicePolicies); + + // ensure the two ranger policies converted into 3 nifi-registry access policies + final Set<AccessPolicy> accessPolicies = pluginWithPolicies.getAccessPolicies(); + assertEquals(3, accessPolicies.size()); + + // resource 1 -> read but no write + assertFalse(pluginWithPolicies.doesPolicyExist(resourceIdentifier1, RequestAction.WRITE)); + assertTrue(pluginWithPolicies.doesPolicyExist(resourceIdentifier1, RequestAction.READ)); + + // read + final AccessPolicy readResource1 = pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.READ); + assertNotNull(readResource1); + assertTrue(accessPolicies.contains(readResource1)); + assertTrue(readResource1.equals(pluginWithPolicies.getAccessPolicy(readResource1.getIdentifier()))); + assertTrue(readResource1.getUsers().isEmpty()); + assertEquals(1, readResource1.getGroups().size()); + assertTrue(readResource1.getGroups().contains(new Group.Builder().identifierGenerateFromSeed(group2).name(group2).build().getIdentifier())); + + // but no write + assertNull(pluginWithPolicies.getAccessPolicy(resourceIdentifier1, RequestAction.WRITE)); + + // resource 2 -> read and write + assertTrue(pluginWithPolicies.doesPolicyExist(resourceIdentifier2, RequestAction.WRITE)); + assertTrue(pluginWithPolicies.doesPolicyExist(resourceIdentifier2, RequestAction.READ)); + + // read + final AccessPolicy readResource2 = pluginWithPolicies.getAccessPolicy(resourceIdentifier2, RequestAction.READ); + assertNotNull(readResource2); + assertTrue(accessPolicies.contains(readResource2)); + assertTrue(readResource2.equals(pluginWithPolicies.getAccessPolicy(readResource2.getIdentifier()))); + assertEquals(1, readResource2.getUsers().size()); + assertTrue(readResource2.getUsers().contains(new User.Builder().identifierGenerateFromSeed(user2).identity(user2).build().getIdentifier())); + assertTrue(readResource2.getGroups().isEmpty()); + + // and write + final AccessPolicy writeResource2 = pluginWithPolicies.getAccessPolicy(resourceIdentifier2, RequestAction.READ); + assertNotNull(writeResource2); + assertTrue(accessPolicies.contains(writeResource2)); + assertTrue(writeResource2.equals(pluginWithPolicies.getAccessPolicy(writeResource2.getIdentifier()))); + assertEquals(1, writeResource2.getUsers().size()); + assertTrue(writeResource2.getUsers().contains(new User.Builder().identifierGenerateFromSeed(user2).identity(user2).build().getIdentifier())); + assertTrue(writeResource2.getGroups().isEmpty()); + } +}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/krb5.conf ---------------------------------------------------------------------- diff --git a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/krb5.conf b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/krb5.conf new file mode 100644 index 0000000..0e3f142 --- /dev/null +++ b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/krb5.conf @@ -0,0 +1,25 @@ +# 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. + +[libdefaults] + default_realm = EXAMPLE.COM + dns_lookup_kdc = false + dns_lookup_realm = false + +[realms] + EXAMPLE.COM = { + kdc = kerberos.example.com + admin_server = kerberos.example.com + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/core-site.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/core-site.xml b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/core-site.xml new file mode 100644 index 0000000..d590a50 --- /dev/null +++ b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/core-site.xml @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> +<!-- + 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. +--> +<configuration> + <property> + <name>hadoop.security.authentication</name> + <value>simple</value> + </property> +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-nifi-registry-audit.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-nifi-registry-audit.xml b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-nifi-registry-audit.xml new file mode 100644 index 0000000..3dbd576 --- /dev/null +++ b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-nifi-registry-audit.xml @@ -0,0 +1,101 @@ +<?xml version="1.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. +--> +<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> +<configuration xmlns:xi="http://www.w3.org/2001/XInclude"> + <property> + <name>xasecure.audit.is.enabled</name> + <value>true</value> + </property> + + <!-- DB audit provider configuration --> + <property> + <name>xasecure.audit.destination.db</name> + <value>false</value> + </property> + + <property> + <name>xasecure.audit.destination.db.jdbc.driver</name> + <value>com.mysql.jdbc.Driver</value> + </property> + + <property> + <name>xasecure.audit.destination.db.jdbc.url</name> + <value>jdbc:mysql://localhost/ranger_audit</value> + </property> + + <property> + <name>xasecure.audit.destination.db.password</name> + <value>rangerlogger</value> + </property> + + <property> + <name>xasecure.audit.destination.db.user</name> + <value>rangerlogger</value> + </property> + + <property> + <name>xasecure.audit.destination.db.batch.filespool.dir</name> + <value>/tmp/audit/db/spool</value> + </property> + + + <!-- HDFS audit provider configuration --> + <property> + <name>xasecure.audit.destination.hdfs</name> + <value>false</value> + </property> + + <property> + <name>xasecure.audit.destination.hdfs.dir</name> + <value>hdfs://localhost:8020/ranger/audit</value> + </property> + + <property> + <name>xasecure.audit.destination.hdfs.batch.filespool.dir</name> + <value>/tmp/audit/hdfs/spool</value> + </property> + + + <!-- Log4j audit provider configuration --> + <property> + <name>xasecure.audit.destination.log4j</name> + <value>false</value> + </property> + + <property> + <name>xasecure.audit.destination.log4j.logger</name> + <value>ranger_audit_logger</value> + </property> + + <!-- Solr audit provider configuration --> + <property> + <name>xasecure.audit.destination.solr</name> + <value>true</value> + </property> + + <property> + <name>xasecure.audit.destination.solr.batch.filespool.dir</name> + <value>/tmp/audit/solr/spool</value> + </property> + + <property> + <name>xasecure.audit.destination.solr.urls</name> + <value>http://localhost:6083/solr/ranger_audits</value> + </property> + +</configuration> http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-nifi-registry-security.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-nifi-registry-security.xml b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-nifi-registry-security.xml new file mode 100644 index 0000000..ab55fba --- /dev/null +++ b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-nifi-registry-security.xml @@ -0,0 +1,83 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> +<!-- + 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. +--> +<configuration> + <property> + <name>ranger.plugin.nifi-registry.policy.rest.url</name> + <value>http://localhost:6080</value> + <description> + URL to Ranger Admin + </description> + </property> + + <property> + <name>ranger.plugin.nifi-registry.service.name</name> + <value>nifi-registry</value> + <description> + Name of the Ranger service containing policies for this nifi instance + </description> + </property> + + <property> + <name>ranger.plugin.nifi-registry.policy.source.impl</name> + <value>org.apache.ranger.admin.client.RangerAdminRESTClient</value> + <description> + Class to retrieve policies from the source + </description> + </property> + + <property> + <name>ranger.plugin.nifi-registry.policy.rest.ssl.config.file</name> + <value>ranger-policymgr-ssl.xml</value> + <description> + Path to the file containing SSL details to contact Ranger Admin + </description> + </property> + + <property> + <name>ranger.plugin.nifi-registry.policy.pollIntervalMs</name> + <value>30000</value> + <description> + How often to poll for changes in policies? + </description> + </property> + + <property> + <name>ranger.plugin.nifi-registry.policy.cache.dir</name> + <value>/tmp</value> + <description> + Directory where Ranger policies are cached after successful retrieval from the source + </description> + </property> + + <property> + <name>ranger.plugin.nifi-registry.policy.rest.client.connection.timeoutMs</name> + <value>120000</value> + <description> + RangerRestClient Connection Timeout in Milli Seconds + </description> + </property> + + <property> + <name>ranger.plugin.nifi-registry.policy.rest.client.read.timeoutMs</name> + <value>30000</value> + <description> + RangerRestClient read Timeout in Milli Seconds + </description> + </property> +</configuration> http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-policymgr-ssl.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-policymgr-ssl.xml b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-policymgr-ssl.xml new file mode 100644 index 0000000..a6e0574 --- /dev/null +++ b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/src/test/resources/ranger/ranger-policymgr-ssl.xml @@ -0,0 +1,63 @@ +<?xml version="1.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. +--> +<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> +<configuration xmlns:xi="http://www.w3.org/2001/XInclude"> + <!-- The following properties are used for 2-way SSL client server validation --> + <property> + <name>xasecure.policymgr.clientssl.keystore</name> + <value></value> + <description> + Java Keystore files + </description> + </property> + <property> + <name>xasecure.policymgr.clientssl.keystore.password</name> + <value>none</value> + <description> + password for keystore + </description> + </property> + <property> + <name>xasecure.policymgr.clientssl.truststore</name> + <value></value> + <description> + java truststore file + </description> + </property> + <property> + <name>xasecure.policymgr.clientssl.truststore.password</name> + <value>none</value> + <description> + java truststore password + </description> + </property> + <property> + <name>xasecure.policymgr.clientssl.keystore.credential.file</name> + <value></value> + <description> + java keystore credential file + </description> + </property> + <property> + <name>xasecure.policymgr.clientssl.truststore.credential.file</name> + <value></value> + <description> + java truststore credential file + </description> + </property> +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-extensions/nifi-registry-ranger/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-extensions/nifi-registry-ranger/pom.xml b/nifi-registry-extensions/nifi-registry-ranger/pom.xml new file mode 100644 index 0000000..1417637 --- /dev/null +++ b/nifi-registry-extensions/nifi-registry-ranger/pom.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>nifi-registry-extensions</artifactId> + <groupId>org.apache.nifi.registry</groupId> + <version>0.3.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>nifi-registry-ranger</artifactId> + <packaging>pom</packaging> + + <modules> + <module>nifi-registry-ranger-assembly</module> + <module>nifi-registry-ranger-jersey-bundle</module> + <module>nifi-registry-ranger-plugin</module> + </modules> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-extensions/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-extensions/pom.xml b/nifi-registry-extensions/pom.xml new file mode 100644 index 0000000..47f8196 --- /dev/null +++ b/nifi-registry-extensions/pom.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>nifi-registry</artifactId> + <groupId>org.apache.nifi.registry</groupId> + <version>0.3.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>nifi-registry-extensions</artifactId> + <packaging>pom</packaging> + + <modules> + <module>nifi-registry-ranger</module> + </modules> + + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java new file mode 100644 index 0000000..b24f950 --- /dev/null +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java @@ -0,0 +1,49 @@ +/* + * 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.nifi.registry.extension; + +import java.io.Closeable; +import java.io.IOException; + +public class ExtensionCloseable implements Closeable { + private final ClassLoader toSet; + + private ExtensionCloseable(ClassLoader toSet) { + this.toSet = toSet; + } + + public static ExtensionCloseable withComponentClassLoader(final ExtensionManager manager, final Class componentClass) { + + final ClassLoader current = Thread.currentThread().getContextClassLoader(); + final ExtensionCloseable closeable = new ExtensionCloseable(current); + + ClassLoader componentClassLoader = manager.getExtensionClassLoader(componentClass.getName()); + if (componentClassLoader == null) { + componentClassLoader = componentClass.getClassLoader(); + } + + Thread.currentThread().setContextClassLoader(componentClassLoader); + return closeable; + } + + @Override + public void close() throws IOException { + if (toSet != null) { + Thread.currentThread().setContextClassLoader(toSet); + } + } +} http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/e1bd6e26/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerCapabilityDetection.java ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerCapabilityDetection.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerCapabilityDetection.java index 5252c7f..0652583 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerCapabilityDetection.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerCapabilityDetection.java @@ -16,15 +16,6 @@ */ package org.apache.nifi.registry.security.authorization; -import org.apache.nifi.registry.security.authorization.AccessPolicy; -import org.apache.nifi.registry.security.authorization.AccessPolicyProvider; -import org.apache.nifi.registry.security.authorization.Authorizer; -import org.apache.nifi.registry.security.authorization.ConfigurableAccessPolicyProvider; -import org.apache.nifi.registry.security.authorization.ConfigurableUserGroupProvider; -import org.apache.nifi.registry.security.authorization.Group; -import org.apache.nifi.registry.security.authorization.ManagedAuthorizer; -import org.apache.nifi.registry.security.authorization.User; - public final class AuthorizerCapabilityDetection { public static boolean isManagedAuthorizer(final Authorizer authorizer) {