http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileUserGroupProviderTest.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileUserGroupProviderTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileUserGroupProviderTest.java new file mode 100644 index 0000000..8b91f78 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileUserGroupProviderTest.java @@ -0,0 +1,698 @@ +/* + * 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.authorization; + +import org.apache.nifi.attribute.expression.language.StandardPropertyValue; +import org.apache.nifi.authorization.exception.AuthorizerCreationException; +import org.apache.nifi.components.PropertyValue; +import org.apache.nifi.util.NiFiProperties; +import org.apache.nifi.util.file.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class FileUserGroupProviderTest { + + private static final String EMPTY_TENANTS_CONCISE = + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<tenants/>"; + + private static final String EMPTY_TENANTS = + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<tenants>" + + "</tenants>"; + + private static final String BAD_SCHEMA_TENANTS = + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<tenant>" + + "</tenant>"; + + private static final String SIMPLE_TENANTS_BY_USER = + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<tenants>" + + " <users>" + + " <user identifier=\"user-1\" identity=\"user-1\"/>" + + " <user identifier=\"user-2\" identity=\"user-2\"/>" + + " </users>" + + "</tenants>"; + + private static final String TENANTS = + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<tenants>" + + " <groups>" + + " <group identifier=\"group-1\" name=\"group-1\">" + + " <user identifier=\"user-1\" />" + + " </group>" + + " <group identifier=\"group-2\" name=\"group-2\">" + + " <user identifier=\"user-2\" />" + + " </group>" + + " </groups>" + + " <users>" + + " <user identifier=\"user-1\" identity=\"user-1\" />" + + " <user identifier=\"user-2\" identity=\"user-2\" />" + + " </users>" + + "</tenants>"; + + private NiFiProperties properties; + private FileUserGroupProvider userGroupProvider; + private File primaryTenants; + private File restoreTenants; + + private AuthorizerConfigurationContext configurationContext; + + @Before + public void setup() throws IOException { + // primary tenants + primaryTenants = new File("target/authorizations/users.xml"); + FileUtils.ensureDirectoryExistAndCanAccess(primaryTenants.getParentFile()); + + // restore authorizations + restoreTenants = new File("target/restore/users.xml"); + FileUtils.ensureDirectoryExistAndCanAccess(restoreTenants.getParentFile()); + + properties = mock(NiFiProperties.class); + when(properties.getRestoreDirectory()).thenReturn(restoreTenants.getParentFile()); + + configurationContext = mock(AuthorizerConfigurationContext.class); + when(configurationContext.getProperty(eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE))).thenReturn(new StandardPropertyValue(null, null)); + when(configurationContext.getProperty(eq(FileUserGroupProvider.PROP_TENANTS_FILE))).thenReturn(new StandardPropertyValue(primaryTenants.getPath(), null)); + when(configurationContext.getProperties()).then((invocation) -> { + final Map<String, String> properties = new HashMap<>(); + + final PropertyValue tenantFile = configurationContext.getProperty(FileUserGroupProvider.PROP_TENANTS_FILE); + if (tenantFile != null) { + properties.put(FileUserGroupProvider.PROP_TENANTS_FILE, tenantFile.getValue()); + } + + final PropertyValue legacyAuthFile = configurationContext.getProperty(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE); + if (legacyAuthFile != null) { + properties.put(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE, legacyAuthFile.getValue()); + } + + int i = 1; + while (true) { + final String key = FileUserGroupProvider.PROP_INITIAL_USER_IDENTITY_PREFIX + i++; + final PropertyValue value = configurationContext.getProperty(key); + if (value == null) { + break; + } else { + properties.put(key, value.getValue()); + } + } + + return properties; + }); + + userGroupProvider = new FileUserGroupProvider(); + userGroupProvider.setNiFiProperties(properties); + userGroupProvider.initialize(null); + } + + @After + public void cleanup() throws Exception { + deleteFile(primaryTenants); + deleteFile(restoreTenants); + } + + @Test + public void testOnConfiguredWhenLegacyUsersFileProvided() throws Exception { + when(configurationContext.getProperty(eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE))) + .thenReturn(new StandardPropertyValue("src/test/resources/authorized-users.xml", null)); + + writeFile(primaryTenants, EMPTY_TENANTS_CONCISE); + userGroupProvider.onConfigured(configurationContext); + + // verify all users got created correctly + final Set<User> users = userGroupProvider.getUsers(); + assertEquals(6, users.size()); + + final User user1 = userGroupProvider.getUserByIdentity("user1"); + assertNotNull(user1); + + final User user2 = userGroupProvider.getUserByIdentity("user2"); + assertNotNull(user2); + + final User user3 = userGroupProvider.getUserByIdentity("user3"); + assertNotNull(user3); + + final User user4 = userGroupProvider.getUserByIdentity("user4"); + assertNotNull(user4); + + final User user5 = userGroupProvider.getUserByIdentity("user5"); + assertNotNull(user5); + + final User user6 = userGroupProvider.getUserByIdentity("user6"); + assertNotNull(user6); + + // verify one group got created + final Set<Group> groups = userGroupProvider.getGroups(); + assertEquals(1, groups.size()); + final Group group1 = groups.iterator().next(); + assertEquals("group1", group1.getName()); + } + + @Test + public void testOnConfiguredWhenLegacyUsersFileProvidedWithIdentityMappings() throws Exception { + final Properties props = new Properties(); + props.setProperty("nifi.security.identity.mapping.pattern.dn1", "^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$"); + props.setProperty("nifi.security.identity.mapping.value.dn1", "$1"); + + properties = getNiFiProperties(props); + when(properties.getRestoreDirectory()).thenReturn(restoreTenants.getParentFile()); + userGroupProvider.setNiFiProperties(properties); + + when(configurationContext.getProperty(eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE))) + .thenReturn(new StandardPropertyValue("src/test/resources/authorized-users-with-dns.xml", null)); + + writeFile(primaryTenants, EMPTY_TENANTS_CONCISE); + userGroupProvider.onConfigured(configurationContext); + + final User user1 = userGroupProvider.getUserByIdentity("user1"); + assertNotNull(user1); + + final User user2 = userGroupProvider.getUserByIdentity("user2"); + assertNotNull(user2); + + final User user3 = userGroupProvider.getUserByIdentity("user3"); + assertNotNull(user3); + + final User user4 = userGroupProvider.getUserByIdentity("user4"); + assertNotNull(user4); + + final User user5 = userGroupProvider.getUserByIdentity("user5"); + assertNotNull(user5); + + final User user6 = userGroupProvider.getUserByIdentity("user6"); + assertNotNull(user6); + + // verify one group got created + final Set<Group> groups = userGroupProvider.getGroups(); + assertEquals(1, groups.size()); + final Group group1 = groups.iterator().next(); + assertEquals("group1", group1.getName()); + } + + @Test(expected = AuthorizerCreationException.class) + public void testOnConfiguredWhenBadLegacyUsersFileProvided() throws Exception { + when(configurationContext.getProperty(eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE))) + .thenReturn(new StandardPropertyValue("src/test/resources/does-not-exist.xml", null)); + + writeFile(primaryTenants, EMPTY_TENANTS_CONCISE); + userGroupProvider.onConfigured(configurationContext); + } + + @Test + public void testOnConfiguredWhenInitialUsersNotProvided() throws Exception { + writeFile(primaryTenants, EMPTY_TENANTS_CONCISE); + userGroupProvider.onConfigured(configurationContext); + + final Set<User> users = userGroupProvider.getUsers(); + assertEquals(0, users.size()); + } + + @Test + public void testOnConfiguredWhenInitialUsersProvided() throws Exception { + final String adminIdentity = "admin-user"; + final String nodeIdentity1 = "node-identity-1"; + final String nodeIdentity2 = "node-identity-2"; + + when(configurationContext.getProperty(eq(FileUserGroupProvider.PROP_INITIAL_USER_IDENTITY_PREFIX + "1"))) + .thenReturn(new StandardPropertyValue(adminIdentity, null)); + when(configurationContext.getProperty(eq(FileUserGroupProvider.PROP_INITIAL_USER_IDENTITY_PREFIX + "2"))) + .thenReturn(new StandardPropertyValue(nodeIdentity1, null)); + when(configurationContext.getProperty(eq(FileUserGroupProvider.PROP_INITIAL_USER_IDENTITY_PREFIX + "3"))) + .thenReturn(new StandardPropertyValue(nodeIdentity2, null)); + + writeFile(primaryTenants, EMPTY_TENANTS_CONCISE); + userGroupProvider.onConfigured(configurationContext); + + final Set<User> users = userGroupProvider.getUsers(); + assertEquals(3, users.size()); + + assertTrue(users.contains(new User.Builder().identifierGenerateFromSeed(adminIdentity).identity(adminIdentity).build())); + assertTrue(users.contains(new User.Builder().identifierGenerateFromSeed(nodeIdentity1).identity(nodeIdentity1).build())); + assertTrue(users.contains(new User.Builder().identifierGenerateFromSeed(nodeIdentity2).identity(nodeIdentity2).build())); + } + + @Test + public void testOnConfiguredWhenTenantsExistAndInitialUsersProvided() throws Exception { + final String adminIdentity = "admin-user"; + final String nodeIdentity1 = "node-identity-1"; + final String nodeIdentity2 = "node-identity-2"; + + // despite setting initial users, they will not be loaded as the tenants file is non-empty + when(configurationContext.getProperty(eq(FileUserGroupProvider.PROP_INITIAL_USER_IDENTITY_PREFIX + "1"))) + .thenReturn(new StandardPropertyValue(adminIdentity, null)); + when(configurationContext.getProperty(eq(FileUserGroupProvider.PROP_INITIAL_USER_IDENTITY_PREFIX + "2"))) + .thenReturn(new StandardPropertyValue(nodeIdentity1, null)); + when(configurationContext.getProperty(eq(FileUserGroupProvider.PROP_INITIAL_USER_IDENTITY_PREFIX + "3"))) + .thenReturn(new StandardPropertyValue(nodeIdentity2, null)); + + writeFile(primaryTenants, SIMPLE_TENANTS_BY_USER); + userGroupProvider.onConfigured(configurationContext); + + final Set<User> users = userGroupProvider.getUsers(); + assertEquals(2, users.size()); + + assertTrue(users.contains(new User.Builder().identifier("user-1").identity("user-1").build())); + assertTrue(users.contains(new User.Builder().identifier("user-2").identity("user-2").build())); + } + + @Test + public void testOnConfiguredWhenTenantsFileDoesNotExist() throws Exception { + writeFile(primaryTenants, EMPTY_TENANTS_CONCISE); + userGroupProvider.onConfigured(configurationContext); + assertEquals(0, userGroupProvider.getUsers().size()); + assertEquals(0, userGroupProvider.getGroups().size()); + } + + @Test + public void testOnConfiguredWhenRestoreDoesNotExist() throws Exception { + writeFile(primaryTenants, EMPTY_TENANTS_CONCISE); + userGroupProvider.onConfigured(configurationContext); + + assertEquals(primaryTenants.length(), restoreTenants.length()); + } + + @Test(expected = AuthorizerCreationException.class) + public void testOnConfiguredWhenPrimaryDoesNotExist() throws Exception { + writeFile(restoreTenants, EMPTY_TENANTS_CONCISE); + userGroupProvider.onConfigured(configurationContext); + } + + + @Test(expected = AuthorizerCreationException.class) + public void testOnConfiguredWhenPrimaryTenantsDifferentThanRestore() throws Exception { + writeFile(primaryTenants, EMPTY_TENANTS); + writeFile(restoreTenants, EMPTY_TENANTS_CONCISE); + userGroupProvider.onConfigured(configurationContext); + } + + @Test(expected = AuthorizerCreationException.class) + public void testOnConfiguredWithBadTenantsSchema() throws Exception { + writeFile(primaryTenants, BAD_SCHEMA_TENANTS); + userGroupProvider.onConfigured(configurationContext); + } + + @Test + public void testGetAllUsersGroupsPolicies() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + + final Set<Group> groups = userGroupProvider.getGroups(); + assertEquals(2, groups.size()); + + boolean foundGroup1 = false; + boolean foundGroup2 = false; + + for (Group group : groups) { + if (group.getIdentifier().equals("group-1") && group.getName().equals("group-1") + && group.getUsers().size() == 1 && group.getUsers().contains("user-1")) { + foundGroup1 = true; + } else if (group.getIdentifier().equals("group-2") && group.getName().equals("group-2") + && group.getUsers().size() == 1 && group.getUsers().contains("user-2")) { + foundGroup2 = true; + } + } + + assertTrue(foundGroup1); + assertTrue(foundGroup2); + + final Set<User> users = userGroupProvider.getUsers(); + assertEquals(2, users.size()); + + boolean foundUser1 = false; + boolean foundUser2 = false; + + for (User user : users) { + if (user.getIdentifier().equals("user-1") && user.getIdentity().equals("user-1")) { + foundUser1 = true; + } else if (user.getIdentifier().equals("user-2") && user.getIdentity().equals("user-2")) { + foundUser2 = true; + } + } + + assertTrue(foundUser1); + assertTrue(foundUser2); + } + + // --------------- User Tests ------------------------ + + @Test + public void testAddUser() throws Exception { + writeFile(primaryTenants, EMPTY_TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(0, userGroupProvider.getUsers().size()); + + final User user = new User.Builder() + .identifier("user-1") + .identity("user-identity-1") + .build(); + + final User addedUser = userGroupProvider.addUser(user); + assertNotNull(addedUser); + assertEquals(user.getIdentifier(), addedUser.getIdentifier()); + assertEquals(user.getIdentity(), addedUser.getIdentity()); + + final Set<User> users = userGroupProvider.getUsers(); + assertEquals(1, users.size()); + } + + @Test + public void testGetUserByIdentifierWhenFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getUsers().size()); + + final String identifier = "user-1"; + final User user = userGroupProvider.getUser(identifier); + assertNotNull(user); + assertEquals(identifier, user.getIdentifier()); + } + + @Test + public void testGetUserByIdentifierWhenNotFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getUsers().size()); + + final String identifier = "user-X"; + final User user = userGroupProvider.getUser(identifier); + assertNull(user); + } + + @Test + public void testGetUserByIdentityWhenFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getUsers().size()); + + final String identity = "user-1"; + final User user = userGroupProvider.getUserByIdentity(identity); + assertNotNull(user); + assertEquals(identity, user.getIdentifier()); + } + + @Test + public void testGetUserByIdentityWhenNotFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getUsers().size()); + + final String identity = "user-X"; + final User user = userGroupProvider.getUserByIdentity(identity); + assertNull(user); + } + + @Test + public void testDeleteUser() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getUsers().size()); + + // retrieve user-1 and verify it exists + final User user = userGroupProvider.getUser("user-1"); + assertEquals("user-1", user.getIdentifier()); + + // delete user-1 + final User deletedUser = userGroupProvider.deleteUser(user); + assertNotNull(deletedUser); + assertEquals("user-1", deletedUser.getIdentifier()); + + // should be one less user + assertEquals(1, userGroupProvider.getUsers().size()); + assertNull(userGroupProvider.getUser(user.getIdentifier())); + } + + @Test + public void testDeleteUserWhenNotFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getUsers().size()); + + //user that doesn't exist + final User user = new User.Builder().identifier("user-X").identity("user-identity-X").build(); + + // should return null and still have 2 users because nothing was deleted + final User deletedUser = userGroupProvider.deleteUser(user); + assertNull(deletedUser); + assertEquals(2, userGroupProvider.getUsers().size()); + } + + @Test + public void testUpdateUserWhenFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getUsers().size()); + + final User user = new User.Builder() + .identifier("user-1") + .identity("new-identity") + .build(); + + final User updatedUser = userGroupProvider.updateUser(user); + assertNotNull(updatedUser); + assertEquals(user.getIdentifier(), updatedUser.getIdentifier()); + assertEquals(user.getIdentity(), updatedUser.getIdentity()); + } + + @Test + public void testUpdateUserWhenNotFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getUsers().size()); + + final User user = new User.Builder() + .identifier("user-X") + .identity("new-identity") + .build(); + + final User updatedUser = userGroupProvider.updateUser(user); + assertNull(updatedUser); + } + + // --------------- Group Tests ------------------------ + + @Test + public void testAddGroup() throws Exception { + writeFile(primaryTenants, EMPTY_TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(0, userGroupProvider.getGroups().size()); + + final Group group = new Group.Builder() + .identifier("group-id-1") + .name("group-name-1") + .build(); + + final Group addedGroup = userGroupProvider.addGroup(group); + assertNotNull(addedGroup); + assertEquals(group.getIdentifier(), addedGroup.getIdentifier()); + assertEquals(group.getName(), addedGroup.getName()); + assertEquals(0, addedGroup.getUsers().size()); + + final Set<Group> groups = userGroupProvider.getGroups(); + assertEquals(1, groups.size()); + } + + @Test + public void testAddGroupWithUser() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getGroups().size()); + + final Group group = new Group.Builder() + .identifier("group-id-XXX") + .name("group-name-XXX") + .addUser("user-1") + .build(); + + final Group addedGroup = userGroupProvider.addGroup(group); + assertNotNull(addedGroup); + assertEquals(group.getIdentifier(), addedGroup.getIdentifier()); + assertEquals(group.getName(), addedGroup.getName()); + assertEquals(1, addedGroup.getUsers().size()); + + final Set<Group> groups = userGroupProvider.getGroups(); + assertEquals(3, groups.size()); + } + + @Test(expected = IllegalStateException.class) + public void testAddGroupWhenUserDoesNotExist() throws Exception { + writeFile(primaryTenants, EMPTY_TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(0, userGroupProvider.getGroups().size()); + + final Group group = new Group.Builder() + .identifier("group-id-1") + .name("group-name-1") + .addUser("user1") + .build(); + + userGroupProvider.addGroup(group); + } + + @Test + public void testGetGroupByIdentifierWhenFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getGroups().size()); + + final String identifier = "group-1"; + final Group group = userGroupProvider.getGroup(identifier); + assertNotNull(group); + assertEquals(identifier, group.getIdentifier()); + } + + @Test + public void testGetGroupByIdentifierWhenNotFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getGroups().size()); + + final String identifier = "group-X"; + final Group group = userGroupProvider.getGroup(identifier); + assertNull(group); + } + + @Test + public void testDeleteGroupWhenFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getGroups().size()); + + // retrieve group-1 + final Group group = userGroupProvider.getGroup("group-1"); + assertEquals("group-1", group.getIdentifier()); + + // delete group-1 + final Group deletedGroup = userGroupProvider.deleteGroup(group); + assertNotNull(deletedGroup); + assertEquals("group-1", deletedGroup.getIdentifier()); + + // verify there is one less overall group + assertEquals(1, userGroupProvider.getGroups().size()); + + // verify we can no longer retrieve group-1 by identifier + assertNull(userGroupProvider.getGroup(group.getIdentifier())); + } + + @Test + public void testDeleteGroupWhenNotFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getGroups().size()); + + final Group group = new Group.Builder() + .identifier("group-id-X") + .name("group-name-X") + .build(); + + final Group deletedGroup = userGroupProvider.deleteGroup(group); + assertNull(deletedGroup); + assertEquals(2, userGroupProvider.getGroups().size()); + } + + @Test + public void testUpdateGroupWhenFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getGroups().size()); + + // verify user-1 is in group-1 before the update + final Group groupBefore = userGroupProvider.getGroup("group-1"); + assertEquals(1, groupBefore.getUsers().size()); + assertTrue(groupBefore.getUsers().contains("user-1")); + + final Group group = new Group.Builder() + .identifier("group-1") + .name("new-name") + .addUser("user-2") + .build(); + + final Group updatedGroup = userGroupProvider.updateGroup(group); + assertEquals(group.getIdentifier(), updatedGroup.getIdentifier()); + assertEquals(group.getName(), updatedGroup.getName()); + + assertEquals(1, updatedGroup.getUsers().size()); + assertTrue(updatedGroup.getUsers().contains("user-2")); + } + + @Test + public void testUpdateGroupWhenNotFound() throws Exception { + writeFile(primaryTenants, TENANTS); + userGroupProvider.onConfigured(configurationContext); + assertEquals(2, userGroupProvider.getGroups().size()); + + final Group group = new Group.Builder() + .identifier("group-X") + .name("group-X") + .build(); + + final Group updatedGroup = userGroupProvider.updateGroup(group); + assertNull(updatedGroup); + assertEquals(2, userGroupProvider.getGroups().size()); + } + + private static void writeFile(final File file, final String content) throws Exception { + byte[] bytes = content.getBytes(StandardCharsets.UTF_8); + try (final FileOutputStream fos = new FileOutputStream(file)) { + fos.write(bytes); + } + } + + private static boolean deleteFile(final File file) { + if (file.isDirectory()) { + FileUtils.deleteFilesInDir(file, null, null, true, true); + } + return FileUtils.deleteFile(file, null, 10); + } + + private NiFiProperties getNiFiProperties(final Properties properties) { + final NiFiProperties nifiProperties = Mockito.mock(NiFiProperties.class); + when(nifiProperties.getPropertyKeys()).thenReturn(properties.stringPropertyNames()); + + when(nifiProperties.getProperty(anyString())).then(new Answer<String>() { + @Override + public String answer(InvocationOnMock invocationOnMock) throws Throwable { + return properties.getProperty((String)invocationOnMock.getArguments()[0]); + } + }); + return nifiProperties; + } + +}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java index 344f49c..58343e8 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java @@ -22,10 +22,15 @@ package org.apache.nifi.authorization; public class StandardAuthorizerInitializationContext implements AuthorizerInitializationContext { private final String identifier; + private final UserGroupProviderLookup userGroupProviderLookup; + private final AccessPolicyProviderLookup accessPolicyProviderLookup; private final AuthorizerLookup authorizerLookup; - public StandardAuthorizerInitializationContext(String identifier, AuthorizerLookup authorizerLookup) { + public StandardAuthorizerInitializationContext(String identifier, UserGroupProviderLookup userGroupProviderLookup, + AccessPolicyProviderLookup accessPolicyProviderLookup, AuthorizerLookup authorizerLookup) { this.identifier = identifier; + this.userGroupProviderLookup = userGroupProviderLookup; + this.accessPolicyProviderLookup = accessPolicyProviderLookup; this.authorizerLookup = authorizerLookup; } @@ -38,4 +43,13 @@ public class StandardAuthorizerInitializationContext implements AuthorizerInitia return authorizerLookup; } + @Override + public AccessPolicyProviderLookup getAccessPolicyProviderLookup() { + return accessPolicyProviderLookup; + } + + @Override + public UserGroupProviderLookup getUserGroupProviderLookup() { + return userGroupProviderLookup; + } } http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardManagedAuthorizer.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardManagedAuthorizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardManagedAuthorizer.java new file mode 100644 index 0000000..8e726f7 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardManagedAuthorizer.java @@ -0,0 +1,251 @@ +/* + * 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.authorization; + +import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authorization.exception.AuthorizationAccessException; +import org.apache.nifi.authorization.exception.AuthorizerCreationException; +import org.apache.nifi.authorization.exception.AuthorizerDestructionException; +import org.apache.nifi.authorization.exception.UninheritableAuthorizationsException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.util.Set; + +public class StandardManagedAuthorizer implements ManagedAuthorizer { + + private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); + private static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newInstance(); + + private static final String USER_GROUP_PROVIDER_ELEMENT = "userGroupProvider"; + private static final String ACCESS_POLICY_PROVIDER_ELEMENT = "accessPolicyProvider"; + + private AccessPolicyProviderLookup accessPolicyProviderLookup; + private AccessPolicyProvider accessPolicyProvider; + private UserGroupProvider userGroupProvider; + + @Override + public void initialize(AuthorizerInitializationContext initializationContext) throws AuthorizerCreationException { + accessPolicyProviderLookup = initializationContext.getAccessPolicyProviderLookup(); + } + + @Override + public void onConfigured(AuthorizerConfigurationContext configurationContext) throws AuthorizerCreationException { + final String accessPolicyProviderKey = configurationContext.getProperty("Access Policy Provider").getValue(); + accessPolicyProvider = accessPolicyProviderLookup.getAccessPolicyProvider(accessPolicyProviderKey); + + // ensure the desired access policy provider was found + if (accessPolicyProvider == null) { + throw new AuthorizerCreationException(String.format("Unable to locate configured Access Policy Provider: %s", accessPolicyProviderKey)); + } + + userGroupProvider = accessPolicyProvider.getUserGroupProvider(); + + // ensure the desired access policy provider has a user group provider + if (userGroupProvider == null) { + throw new AuthorizerCreationException(String.format("Configured Access Policy Provider %s does not contain a User Group Provider", accessPolicyProviderKey)); + } + } + + @Override + public AuthorizationResult authorize(AuthorizationRequest request) throws AuthorizationAccessException { + final String resourceIdentifier = request.getResource().getIdentifier(); + final AccessPolicy policy = accessPolicyProvider.getAccessPolicy(resourceIdentifier, request.getAction()); + if (policy == null) { + return AuthorizationResult.resourceNotFound(); + } + + final UserAndGroups userAndGroups = userGroupProvider.getUserAndGroups(request.getIdentity()); + + final User user = userAndGroups.getUser(); + if (user == null) { + return AuthorizationResult.denied(String.format("Unknown user with identity '%s'.", request.getIdentity())); + } + + final Set<Group> userGroups = userAndGroups.getGroups(); + if (policy.getUsers().contains(user.getIdentifier()) || containsGroup(userGroups, policy)) { + return AuthorizationResult.approved(); + } + + return AuthorizationResult.denied(request.getExplanationSupplier().get()); + } + + /** + * Determines if the policy contains one of the user's groups. + * + * @param userGroups the set of the user's groups + * @param policy the policy + * @return true if one of the Groups in userGroups is contained in the policy + */ + private boolean containsGroup(final Set<Group> userGroups, final AccessPolicy policy) { + if (userGroups == null || userGroups.isEmpty() || policy.getGroups().isEmpty()) { + return false; + } + + for (Group userGroup : userGroups) { + if (policy.getGroups().contains(userGroup.getIdentifier())) { + return true; + } + } + + return false; + } + + @Override + public String getFingerprint() throws AuthorizationAccessException { + XMLStreamWriter writer = null; + final StringWriter out = new StringWriter(); + try { + writer = XML_OUTPUT_FACTORY.createXMLStreamWriter(out); + writer.writeStartDocument(); + writer.writeStartElement("managedAuthorizations"); + + writer.writeStartElement(ACCESS_POLICY_PROVIDER_ELEMENT); + if (accessPolicyProvider instanceof ConfigurableAccessPolicyProvider) { + writer.writeCharacters(((ConfigurableAccessPolicyProvider) accessPolicyProvider).getFingerprint()); + } + writer.writeEndElement(); + + writer.writeStartElement(USER_GROUP_PROVIDER_ELEMENT); + if (userGroupProvider instanceof ConfigurableUserGroupProvider) { + writer.writeCharacters(((ConfigurableUserGroupProvider) userGroupProvider).getFingerprint()); + } + writer.writeEndElement(); + + writer.writeEndElement(); + writer.writeEndDocument(); + writer.flush(); + } catch (XMLStreamException e) { + throw new AuthorizationAccessException("Unable to generate fingerprint", e); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (XMLStreamException e) { + // nothing to do here + } + } + } + + return out.toString(); + } + + @Override + public void inheritFingerprint(String fingerprint) throws AuthorizationAccessException { + if (StringUtils.isBlank(fingerprint)) { + return; + } + + final FingerprintHolder fingerprintHolder = parseFingerprint(fingerprint); + + if (StringUtils.isNotBlank(fingerprintHolder.getPolicyFingerprint()) && accessPolicyProvider instanceof ConfigurableAccessPolicyProvider) { + ((ConfigurableAccessPolicyProvider) accessPolicyProvider).inheritFingerprint(fingerprintHolder.getPolicyFingerprint()); + } + + if (StringUtils.isNotBlank(fingerprintHolder.getUserGroupFingerprint()) && userGroupProvider instanceof ConfigurableUserGroupProvider) { + ((ConfigurableUserGroupProvider) userGroupProvider).inheritFingerprint(fingerprintHolder.getUserGroupFingerprint()); + } + } + + @Override + public void checkInheritability(String proposedFingerprint) throws AuthorizationAccessException, UninheritableAuthorizationsException { + final FingerprintHolder fingerprintHolder = parseFingerprint(proposedFingerprint); + + if (StringUtils.isNotBlank(fingerprintHolder.getPolicyFingerprint())) { + if (accessPolicyProvider instanceof ConfigurableAccessPolicyProvider) { + ((ConfigurableAccessPolicyProvider) accessPolicyProvider).checkInheritability(fingerprintHolder.getPolicyFingerprint()); + } else { + throw new UninheritableAuthorizationsException("Policy fingerprint is not blank and the configured AccessPolicyProvider does not support fingerprinting."); + } + } + + if (StringUtils.isNotBlank(fingerprintHolder.getUserGroupFingerprint())) { + if (userGroupProvider instanceof ConfigurableUserGroupProvider) { + ((ConfigurableUserGroupProvider) userGroupProvider).checkInheritability(fingerprintHolder.getUserGroupFingerprint()); + } else { + throw new UninheritableAuthorizationsException("User/Group fingerprint is not blank and the configured UserGroupProvider does not support fingerprinting."); + } + } + } + + private final FingerprintHolder parseFingerprint(final String fingerprint) throws AuthorizationAccessException { + final byte[] fingerprintBytes = fingerprint.getBytes(StandardCharsets.UTF_8); + + try (final ByteArrayInputStream in = new ByteArrayInputStream(fingerprintBytes)) { + final DocumentBuilder docBuilder = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder(); + final Document document = docBuilder.parse(in); + final Element rootElement = document.getDocumentElement(); + + final NodeList accessPolicyProviderList = rootElement.getElementsByTagName(ACCESS_POLICY_PROVIDER_ELEMENT); + if (accessPolicyProviderList.getLength() != 1) { + throw new AuthorizationAccessException(String.format("Only one %s element is allowed: %s", ACCESS_POLICY_PROVIDER_ELEMENT, fingerprint)); + } + + final NodeList userGroupProviderList = rootElement.getElementsByTagName(USER_GROUP_PROVIDER_ELEMENT); + if (userGroupProviderList.getLength() != 1) { + throw new AuthorizationAccessException(String.format("Only one %s element is allowed: %s", USER_GROUP_PROVIDER_ELEMENT, fingerprint)); + } + + final Node accessPolicyProvider = accessPolicyProviderList.item(0); + final Node userGroupProvider = userGroupProviderList.item(0); + return new FingerprintHolder(accessPolicyProvider.getTextContent(), userGroupProvider.getTextContent()); + } catch (SAXException | ParserConfigurationException | IOException e) { + throw new AuthorizationAccessException("Unable to parse fingerprint", e); + } + } + + @Override + public AccessPolicyProvider getAccessPolicyProvider() { + return accessPolicyProvider; + } + + @Override + public void preDestruction() throws AuthorizerDestructionException { + + } + + private static class FingerprintHolder { + private final String policyFingerprint; + private final String userGroupFingerprint; + + public FingerprintHolder(String policyFingerprint, String userGroupFingerprint) { + this.policyFingerprint = policyFingerprint; + this.userGroupFingerprint = userGroupFingerprint; + } + + public String getPolicyFingerprint() { + return policyFingerprint; + } + + public String getUserGroupFingerprint() { + return userGroupFingerprint; + } + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java index 2a82795..8c1619a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java @@ -16,7 +16,11 @@ */ package org.apache.nifi.authorization.user; +import org.apache.commons.lang3.StringUtils; + +import java.util.Collections; import java.util.Objects; +import java.util.Set; /** * An implementation of NiFiUser. @@ -24,42 +28,20 @@ import java.util.Objects; public class StandardNiFiUser implements NiFiUser { public static final String ANONYMOUS_IDENTITY = "anonymous"; - public static final StandardNiFiUser ANONYMOUS = new StandardNiFiUser(ANONYMOUS_IDENTITY, null, null, true); + public static final StandardNiFiUser ANONYMOUS = new Builder().identity(ANONYMOUS_IDENTITY).anonymous(true).build(); private final String identity; + private final Set<String> groups; private final NiFiUser chain; private final String clientAddress; private final boolean isAnonymous; - public StandardNiFiUser(String identity) { - this(identity, null, null, false); - } - - public StandardNiFiUser(String identity, String clientAddress) { - this(identity, null, clientAddress, false); - } - - public StandardNiFiUser(String identity, NiFiUser chain) { - this(identity, chain, null, false); - } - - public StandardNiFiUser(String identity, NiFiUser chain, String clientAddress) { - this(identity, chain, clientAddress, false); - } - - /** - * This constructor is private as the only instance of this class which should have {@code isAnonymous} set to true is the singleton ANONYMOUS. - * - * @param identity the identity string for the user (i.e. "Andy" or "CN=alopresto, OU=Apache NiFi") - * @param chain the proxy chain that leads to this users - * @param clientAddress the source address of the request - * @param isAnonymous true to represent the canonical "anonymous" user - */ - private StandardNiFiUser(String identity, NiFiUser chain, String clientAddress, boolean isAnonymous) { - this.identity = identity; - this.chain = chain; - this.clientAddress = clientAddress; - this.isAnonymous = isAnonymous; + private StandardNiFiUser(final Builder builder) { + this.identity = builder.identity; + this.groups = builder.groups == null ? null : Collections.unmodifiableSet(builder.groups); + this.chain = builder.chain; + this.clientAddress = builder.clientAddress; + this.isAnonymous = builder.isAnonymous; } /** @@ -70,7 +52,7 @@ public class StandardNiFiUser implements NiFiUser { * @return an anonymous user instance with the identity "anonymous" */ public static StandardNiFiUser populateAnonymousUser(NiFiUser chain, String clientAddress) { - return new StandardNiFiUser(ANONYMOUS_IDENTITY, chain, clientAddress, true); + return new Builder().identity(ANONYMOUS_IDENTITY).chain(chain).clientAddress(clientAddress).anonymous(true).build(); } @Override @@ -79,6 +61,11 @@ public class StandardNiFiUser implements NiFiUser { } @Override + public Set<String> getGroups() { + return groups; + } + + @Override public NiFiUser getChain() { return chain; } @@ -116,6 +103,87 @@ public class StandardNiFiUser implements NiFiUser { @Override public String toString() { - return String.format("identity[%s]", getIdentity()); + final String formattedGroups; + if (groups == null) { + formattedGroups = "none"; + } else { + formattedGroups = StringUtils.join(groups, ", "); + } + + return String.format("identity[%s], groups[%s]", getIdentity(), formattedGroups); + } + + /** + * Builder for a StandardNiFiUser + */ + public static class Builder { + + private String identity; + private Set<String> groups; + private NiFiUser chain; + private String clientAddress; + private boolean isAnonymous = false; + + /** + * Sets the identity. + * + * @param identity the identity string for the user (i.e. "Andy" or "CN=alopresto, OU=Apache NiFi") + * @return the builder + */ + public Builder identity(final String identity) { + this.identity = identity; + return this; + } + + /** + * Sets the groups. + * + * @param groups the user groups + * @return the builder + */ + public Builder groups(final Set<String> groups) { + this.groups = groups; + return this; + } + + /** + * Sets the chain. + * + * @param chain the proxy chain that leads to this users + * @return the builder + */ + public Builder chain(final NiFiUser chain) { + this.chain = chain; + return this; + } + + /** + * Sets the client address. + * + * @param clientAddress the source address of the request + * @return the builder + */ + public Builder clientAddress(final String clientAddress) { + this.clientAddress = clientAddress; + return this; + } + + /** + * Sets whether this user is the canonical "anonymous" user + * + * @param isAnonymous true to represent the canonical "anonymous" user + * @return the builder + */ + private Builder anonymous(final boolean isAnonymous) { + this.isAnonymous = isAnonymous; + return this; + } + + /** + * @return builds a StandardNiFiUser from the current state of the builder + */ + public StandardNiFiUser build() { + return new StandardNiFiUser(this); + } } } http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/util/UserGroupUtil.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/util/UserGroupUtil.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/util/UserGroupUtil.java new file mode 100644 index 0000000..a4dc27e --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/util/UserGroupUtil.java @@ -0,0 +1,54 @@ +/* + * 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.authorization.util; + +import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.authorization.Group; +import org.apache.nifi.authorization.ManagedAuthorizer; +import org.apache.nifi.authorization.UserAndGroups; +import org.apache.nifi.authorization.UserGroupProvider; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; + +public class UserGroupUtil { + + /** + * Gets the groups for the user with the specified identity. Returns null if the authorizer is not able to load user groups. + * + * @param authorizer the authorizer to load the groups from + * @param userIdentity the user identity + * @return the listing of groups for the user + */ + public static Set<String> getUserGroups(final Authorizer authorizer, final String userIdentity) { + if (authorizer instanceof ManagedAuthorizer) { + final ManagedAuthorizer managedAuthorizer = (ManagedAuthorizer) authorizer; + final UserGroupProvider userGroupProvider = managedAuthorizer.getAccessPolicyProvider().getUserGroupProvider(); + final UserAndGroups userAndGroups = userGroupProvider.getUserAndGroups(userIdentity); + final Set<Group> userGroups = userAndGroups.getGroups(); + + if (userGroups == null || userGroups.isEmpty()) { + return Collections.EMPTY_SET; + } else { + return userAndGroups.getGroups().stream().map(group -> group.getName()).collect(Collectors.toSet()); + } + } else { + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/resources/META-INF/services/org.apache.nifi.authorization.Authorizer ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/resources/META-INF/services/org.apache.nifi.authorization.Authorizer b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/resources/META-INF/services/org.apache.nifi.authorization.Authorizer new file mode 100755 index 0000000..966a289 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/resources/META-INF/services/org.apache.nifi.authorization.Authorizer @@ -0,0 +1,15 @@ +# 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. +org.apache.nifi.authorization.StandardManagedAuthorizer http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/StandardManagedAuthorizerTest.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/StandardManagedAuthorizerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/StandardManagedAuthorizerTest.java new file mode 100644 index 0000000..a40c6f9 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/StandardManagedAuthorizerTest.java @@ -0,0 +1,438 @@ +/* + * 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.authorization; + + +import org.apache.nifi.attribute.expression.language.StandardPropertyValue; +import org.apache.nifi.authorization.exception.AuthorizationAccessException; +import org.apache.nifi.authorization.exception.AuthorizerCreationException; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; +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.assertTrue; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class StandardManagedAuthorizerTest { + + private static final String EMPTY_FINGERPRINT = "<?xml version=\"1.0\" ?>" + + "<managedAuthorizations>" + + "<accessPolicyProvider></accessPolicyProvider>" + + "<userGroupProvider></userGroupProvider>" + + "</managedAuthorizations>"; + + private static final String NON_EMPTY_FINGERPRINT = "<?xml version=\"1.0\" ?>" + + "<managedAuthorizations>" + + "<accessPolicyProvider>" + + "<accessPolicies>" + + "<policy identifier=\"policy-id-1\" resource=\"resource2\" actions=\"READ\">" + + "<policyUser identifier=\"user-id-1\"></policyUser>" + + "<policyGroup identifier=\"group-id-1\"></policyGroup>" + + "</policy>" + + "</accessPolicies>" + + "</accessPolicyProvider>" + + "<userGroupProvider>" + + "<tenants>" + + "<user identifier=\"user-id-1\" identity=\"user-1\"></user>" + + "<group identifier=\"group-id-1\" name=\"group-1\">" + + "<groupUser identifier=\"user-id-1\"></groupUser>" + + "</group>" + + "</tenants>" + + "</userGroupProvider>" + + "</managedAuthorizations>"; + + private static final String ACCESS_POLICY_FINGERPRINT = + "<accessPolicies>" + + "<policy identifier=\"policy-id-1\" resource=\"resource2\" actions=\"READ\">" + + "<policyUser identifier=\"user-id-1\"></policyUser>" + + "<policyGroup identifier=\"group-id-1\"></policyGroup>" + + "</policy>" + + "</accessPolicies>"; + + private static final String TENANT_FINGERPRINT = + "<tenants>" + + "<user identifier=\"user-id-1\" identity=\"user-1\"></user>" + + "<group identifier=\"group-id-1\" name=\"group-1\">" + + "<groupUser identifier=\"user-id-1\"></groupUser>" + + "</group>" + + "</tenants>"; + + private static final Resource TEST_RESOURCE = new Resource() { + @Override + public String getIdentifier() { + return "1"; + } + + @Override + public String getName() { + return "resource1"; + } + + @Override + public String getSafeDescription() { + return "description1"; + } + }; + + @Test(expected = AuthorizerCreationException.class) + public void testNullAccessPolicyProvider() throws Exception { + getStandardManagedAuthorizer(null); + } + + @Test + public void testEmptyFingerPrint() throws Exception { + final UserGroupProvider userGroupProvider = mock(UserGroupProvider.class); + + final AccessPolicyProvider accessPolicyProvider = mock(AccessPolicyProvider.class); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + Assert.assertEquals(EMPTY_FINGERPRINT, managedAuthorizer.getFingerprint()); + } + + @Test + public void testNonEmptyFingerPrint() throws Exception { + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + when(userGroupProvider.getFingerprint()).thenReturn(TENANT_FINGERPRINT); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getFingerprint()).thenReturn(ACCESS_POLICY_FINGERPRINT); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + Assert.assertEquals(NON_EMPTY_FINGERPRINT, managedAuthorizer.getFingerprint()); + } + + @Test + public void testInheritEmptyFingerprint() throws Exception { + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + managedAuthorizer.inheritFingerprint(EMPTY_FINGERPRINT); + + verify(userGroupProvider, times(0)).inheritFingerprint(anyString()); + verify(accessPolicyProvider, times(0)).inheritFingerprint(anyString()); + } + + @Test(expected = AuthorizationAccessException.class) + public void testInheritInvalidFingerprint() throws Exception { + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + managedAuthorizer.inheritFingerprint("not a valid fingerprint"); + } + + @Test + public void testInheritNonEmptyFingerprint() throws Exception { + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + managedAuthorizer.inheritFingerprint(NON_EMPTY_FINGERPRINT); + + verify(userGroupProvider, times(1)).inheritFingerprint(TENANT_FINGERPRINT); + verify(accessPolicyProvider, times(1)).inheritFingerprint(ACCESS_POLICY_FINGERPRINT); + } + + @Test + public void testCheckInheritEmptyFingerprint() throws Exception { + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + managedAuthorizer.checkInheritability(EMPTY_FINGERPRINT); + + verify(userGroupProvider, times(0)).inheritFingerprint(anyString()); + verify(accessPolicyProvider, times(0)).inheritFingerprint(anyString()); + } + + @Test(expected = AuthorizationAccessException.class) + public void testCheckInheritInvalidFingerprint() throws Exception { + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + managedAuthorizer.checkInheritability("not a valid fingerprint"); + } + + @Test + public void testCheckInheritNonEmptyFingerprint() throws Exception { + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + managedAuthorizer.checkInheritability(NON_EMPTY_FINGERPRINT); + + verify(userGroupProvider, times(1)).checkInheritability(TENANT_FINGERPRINT); + verify(accessPolicyProvider, times(1)).checkInheritability(ACCESS_POLICY_FINGERPRINT); + } + + @Test + public void testAuthorizationByUser() throws Exception { + final String userIdentifier = "userIdentifier1"; + final String userIdentity = "userIdentity1"; + + final User user = new User.Builder() + .identity(userIdentity) + .identifier(userIdentifier) + .build(); + + final AccessPolicy policy = new AccessPolicy.Builder() + .identifier("1") + .resource(TEST_RESOURCE.getIdentifier()) + .addUser(userIdentifier) + .action(RequestAction.READ) + .build(); + + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + when(userGroupProvider.getUserAndGroups(userIdentity)).thenReturn(new UserAndGroups() { + @Override + public User getUser() { + return user; + } + + @Override + public Set<Group> getGroups() { + return Collections.EMPTY_SET; + } + }); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getAccessPolicy(TEST_RESOURCE.getIdentifier(), RequestAction.READ)).thenReturn(policy); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(userIdentity) + .resource(TEST_RESOURCE) + .action(RequestAction.READ) + .accessAttempt(true) + .anonymous(false) + .build(); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + assertEquals(AuthorizationResult.approved(), managedAuthorizer.authorize(request)); + } + + @Test + public void testAuthorizationByGroup() throws Exception { + final String userIdentifier = "userIdentifier1"; + final String userIdentity = "userIdentity1"; + final String groupIdentifier = "groupIdentifier1"; + + final User user = new User.Builder() + .identity(userIdentity) + .identifier(userIdentifier) + .build(); + + final Group group = new Group.Builder() + .identifier(groupIdentifier) + .name(groupIdentifier) + .addUser(user.getIdentifier()) + .build(); + + final AccessPolicy policy = new AccessPolicy.Builder() + .identifier("1") + .resource(TEST_RESOURCE.getIdentifier()) + .addGroup(groupIdentifier) + .action(RequestAction.READ) + .build(); + + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + when(userGroupProvider.getUserAndGroups(userIdentity)).thenReturn(new UserAndGroups() { + @Override + public User getUser() { + return user; + } + + @Override + public Set<Group> getGroups() { + return Stream.of(group).collect(Collectors.toSet()); + } + }); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getAccessPolicy(TEST_RESOURCE.getIdentifier(), RequestAction.READ)).thenReturn(policy); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(userIdentity) + .resource(TEST_RESOURCE) + .action(RequestAction.READ) + .accessAttempt(true) + .anonymous(false) + .build(); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + assertEquals(AuthorizationResult.approved(), managedAuthorizer.authorize(request)); + } + + @Test + public void testResourceNotFound() throws Exception { + final String userIdentity = "userIdentity1"; + + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getAccessPolicy(TEST_RESOURCE.getIdentifier(), RequestAction.READ)).thenReturn(null); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(userIdentity) + .resource(TEST_RESOURCE) + .action(RequestAction.READ) + .accessAttempt(true) + .anonymous(false) + .build(); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + assertEquals(AuthorizationResult.resourceNotFound(), managedAuthorizer.authorize(request)); + } + + @Test + public void testUnauthorizedDueToUnknownUser() throws Exception { + final String userIdentifier = "userIdentifier1"; + final String userIdentity = "userIdentity1"; + final String notUser1Identity = "not userIdentity1"; + + final User user = new User.Builder() + .identity(userIdentity) + .identifier(userIdentifier) + .build(); + + final AccessPolicy policy = new AccessPolicy.Builder() + .identifier("1") + .resource(TEST_RESOURCE.getIdentifier()) + .addUser(userIdentifier) + .action(RequestAction.READ) + .build(); + + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + when(userGroupProvider.getUserAndGroups(notUser1Identity)).thenReturn(new UserAndGroups() { + @Override + public User getUser() { + return null; + } + + @Override + public Set<Group> getGroups() { + return Collections.EMPTY_SET; + } + }); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getAccessPolicy(TEST_RESOURCE.getIdentifier(), RequestAction.READ)).thenReturn(policy); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(notUser1Identity) + .resource(TEST_RESOURCE) + .action(RequestAction.READ) + .accessAttempt(true) + .anonymous(false) + .build(); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + assertTrue(AuthorizationResult.denied().getResult().equals(managedAuthorizer.authorize(request).getResult())); + } + + @Test + public void testUnauthorizedDueToLackOfPermission() throws Exception { + final String userIdentifier = "userIdentifier1"; + final String userIdentity = "userIdentity1"; + + final User user = new User.Builder() + .identity(userIdentity) + .identifier(userIdentifier) + .build(); + + final AccessPolicy policy = new AccessPolicy.Builder() + .identifier("1") + .resource(TEST_RESOURCE.getIdentifier()) + .addUser("userIdentity2") + .action(RequestAction.READ) + .build(); + + final ConfigurableUserGroupProvider userGroupProvider = mock(ConfigurableUserGroupProvider.class); + when(userGroupProvider.getUserAndGroups(userIdentity)).thenReturn(new UserAndGroups() { + @Override + public User getUser() { + return user; + } + + @Override + public Set<Group> getGroups() { + return Collections.EMPTY_SET; + } + }); + + final ConfigurableAccessPolicyProvider accessPolicyProvider = mock(ConfigurableAccessPolicyProvider.class); + when(accessPolicyProvider.getAccessPolicy(TEST_RESOURCE.getIdentifier(), RequestAction.READ)).thenReturn(policy); + when(accessPolicyProvider.getUserGroupProvider()).thenReturn(userGroupProvider); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(userIdentity) + .resource(TEST_RESOURCE) + .action(RequestAction.READ) + .accessAttempt(true) + .anonymous(false) + .build(); + + final StandardManagedAuthorizer managedAuthorizer = getStandardManagedAuthorizer(accessPolicyProvider); + assertTrue(AuthorizationResult.denied().getResult().equals(managedAuthorizer.authorize(request).getResult())); + } + + private StandardManagedAuthorizer getStandardManagedAuthorizer(final AccessPolicyProvider accessPolicyProvider) { + final StandardManagedAuthorizer managedAuthorizer = new StandardManagedAuthorizer(); + + final AuthorizerConfigurationContext configurationContext = mock(AuthorizerConfigurationContext.class); + when(configurationContext.getProperty("Access Policy Provider")).thenReturn(new StandardPropertyValue("access-policy-provider", null)); + + final AccessPolicyProviderLookup accessPolicyProviderLookup = mock(AccessPolicyProviderLookup.class); + when(accessPolicyProviderLookup.getAccessPolicyProvider("access-policy-provider")).thenReturn(accessPolicyProvider); + + final AuthorizerInitializationContext initializationContext = mock(AuthorizerInitializationContext.class); + when(initializationContext.getAccessPolicyProviderLookup()).thenReturn(accessPolicyProviderLookup); + + managedAuthorizer.initialize(initializationContext); + managedAuthorizer.onConfigured(configurationContext); + + return managedAuthorizer; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/resource/DataAuthorizableTest.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/resource/DataAuthorizableTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/resource/DataAuthorizableTest.java index 069bf79..003835f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/resource/DataAuthorizableTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/resource/DataAuthorizableTest.java @@ -16,14 +16,6 @@ */ package org.apache.nifi.authorization.resource; -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import org.apache.nifi.authorization.AccessDeniedException; import org.apache.nifi.authorization.AuthorizationRequest; import org.apache.nifi.authorization.AuthorizationResult; @@ -31,11 +23,19 @@ import org.apache.nifi.authorization.AuthorizationResult.Result; import org.apache.nifi.authorization.Authorizer; import org.apache.nifi.authorization.RequestAction; import org.apache.nifi.authorization.user.NiFiUser; -import org.apache.nifi.authorization.user.StandardNiFiUser; +import org.apache.nifi.authorization.user.StandardNiFiUser.Builder; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentMatcher; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + public class DataAuthorizableTest { private static final String IDENTITY_1 = "identity-1"; @@ -83,20 +83,20 @@ public class DataAuthorizableTest { @Test(expected = AccessDeniedException.class) public void testAuthorizeUnauthorizedUser() { - final NiFiUser user = new StandardNiFiUser("unknown"); + final NiFiUser user = new Builder().identity("unknown").build(); testDataAuthorizable.authorize(testAuthorizer, RequestAction.READ, user, null); } @Test public void testCheckAuthorizationUnauthorizedUser() { - final NiFiUser user = new StandardNiFiUser("unknown"); + final NiFiUser user = new Builder().identity("unknown").build(); final AuthorizationResult result = testDataAuthorizable.checkAuthorization(testAuthorizer, RequestAction.READ, user, null); assertEquals(Result.Denied, result.getResult()); } @Test public void testAuthorizedUser() { - final NiFiUser user = new StandardNiFiUser(IDENTITY_1); + final NiFiUser user = new Builder().identity(IDENTITY_1).build(); testDataAuthorizable.authorize(testAuthorizer, RequestAction.READ, user, null); verify(testAuthorizer, times(1)).authorize(argThat(new ArgumentMatcher<AuthorizationRequest>() { @@ -109,7 +109,7 @@ public class DataAuthorizableTest { @Test public void testCheckAuthorizationUser() { - final NiFiUser user = new StandardNiFiUser(IDENTITY_1); + final NiFiUser user = new Builder().identity(IDENTITY_1).build(); final AuthorizationResult result = testDataAuthorizable.checkAuthorization(testAuthorizer, RequestAction.READ, user, null); assertEquals(Result.Approved, result.getResult()); @@ -123,9 +123,9 @@ public class DataAuthorizableTest { @Test public void testAuthorizedUserChain() { - final NiFiUser proxy2 = new StandardNiFiUser(PROXY_2); - final NiFiUser proxy1 = new StandardNiFiUser(PROXY_1, proxy2); - final NiFiUser user = new StandardNiFiUser(IDENTITY_1, proxy1); + final NiFiUser proxy2 = new Builder().identity(PROXY_2).build(); + final NiFiUser proxy1 = new Builder().identity(PROXY_1).chain(proxy2).build(); + final NiFiUser user = new Builder().identity(IDENTITY_1).chain(proxy1).build(); testDataAuthorizable.authorize(testAuthorizer, RequestAction.READ, user, null); verify(testAuthorizer, times(3)).authorize(any(AuthorizationRequest.class)); @@ -136,9 +136,9 @@ public class DataAuthorizableTest { @Test public void testCheckAuthorizationUserChain() { - final NiFiUser proxy2 = new StandardNiFiUser(PROXY_2); - final NiFiUser proxy1 = new StandardNiFiUser(PROXY_1, proxy2); - final NiFiUser user = new StandardNiFiUser(IDENTITY_1, proxy1); + final NiFiUser proxy2 = new Builder().identity(PROXY_2).build(); + final NiFiUser proxy1 = new Builder().identity(PROXY_1).chain(proxy2).build(); + final NiFiUser user = new Builder().identity(IDENTITY_1).chain(proxy1).build(); final AuthorizationResult result = testDataAuthorizable.checkAuthorization(testAuthorizer, RequestAction.READ, user, null); assertEquals(Result.Approved, result.getResult()); http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/StandardHttpResponseMapper.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/StandardHttpResponseMapper.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/StandardHttpResponseMapper.java index bbaeb26..2fc55a4 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/StandardHttpResponseMapper.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/StandardHttpResponseMapper.java @@ -16,6 +16,7 @@ */ package org.apache.nifi.cluster.coordination.http; +import org.apache.nifi.cluster.coordination.http.endpoints.AccessPolicyEndpointMerger; import org.apache.nifi.cluster.coordination.http.endpoints.BulletinBoardEndpointMerger; import org.apache.nifi.cluster.coordination.http.endpoints.ComponentStateEndpointMerger; import org.apache.nifi.cluster.coordination.http.endpoints.ConnectionEndpointMerger; @@ -60,9 +61,14 @@ import org.apache.nifi.cluster.coordination.http.endpoints.RemoteProcessGroupsEn import org.apache.nifi.cluster.coordination.http.endpoints.ReportingTaskEndpointMerger; import org.apache.nifi.cluster.coordination.http.endpoints.ReportingTaskTypesEndpointMerger; import org.apache.nifi.cluster.coordination.http.endpoints.ReportingTasksEndpointMerger; +import org.apache.nifi.cluster.coordination.http.endpoints.SearchUsersEndpointMerger; import org.apache.nifi.cluster.coordination.http.endpoints.StatusHistoryEndpointMerger; import org.apache.nifi.cluster.coordination.http.endpoints.SystemDiagnosticsEndpointMerger; import org.apache.nifi.cluster.coordination.http.endpoints.TemplatesEndpointMerger; +import org.apache.nifi.cluster.coordination.http.endpoints.UserEndpointMerger; +import org.apache.nifi.cluster.coordination.http.endpoints.UserGroupEndpointMerger; +import org.apache.nifi.cluster.coordination.http.endpoints.UserGroupsEndpointMerger; +import org.apache.nifi.cluster.coordination.http.endpoints.UsersEndpointMerger; import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator; import org.apache.nifi.cluster.manager.NodeResponse; import org.apache.nifi.stream.io.NullOutputStream; @@ -141,6 +147,12 @@ public class StandardHttpResponseMapper implements HttpResponseMapper { endpointMergers.add(new FunnelEndpointMerger()); endpointMergers.add(new FunnelsEndpointMerger()); endpointMergers.add(new ControllerEndpointMerger()); + endpointMergers.add(new UsersEndpointMerger()); + endpointMergers.add(new UserEndpointMerger()); + endpointMergers.add(new UserGroupsEndpointMerger()); + endpointMergers.add(new UserGroupEndpointMerger()); + endpointMergers.add(new AccessPolicyEndpointMerger()); + endpointMergers.add(new SearchUsersEndpointMerger()); } @Override
