You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by bb...@apache.org on 2017/06/09 17:55:11 UTC
[04/11] nifi git commit: NIFI-3653: - Introducing UserGroup and
Policy provider interfaces. - Introducing FileUserGroupProvider and
FileAccessPolicyProvider. - Refactoring FileAuthorizer to utilize the file
based implementations. - Introducing the Standa
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