Repository: nifi
Updated Branches:
  refs/heads/master db9a79f79 -> 679ad93f5


NIFI-1804 Adding ability for FileAuthorizer to automatically convert existing 
authorized-users.xml to new model
- Removing Resources class from file authorizer and updating ResourceType enum
- Updating ResourceFactory to be in sync with ResourceType enum and adding 
additional required permissions to the auto-conversion
- Adding root process group to the seeding of the initial admin
- Improvement so that users that are already part of a read-write policy, won't 
end up in a read policy for the same resource
- Removing rootGroupId from authorization context and auto-detecting it from 
the flow provided through nifi.properties
- This closes #507


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/679ad93f
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/679ad93f
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/679ad93f

Branch: refs/heads/master
Commit: 679ad93f577e70d5d322fe368a5c333b525fb6da
Parents: db9a79f
Author: Bryan Bende <[email protected]>
Authored: Mon Jun 6 16:32:19 2016 -0400
Committer: Matt Gilman <[email protected]>
Committed: Fri Jun 17 16:33:00 2016 -0400

----------------------------------------------------------------------
 .../AuthorizerConfigurationContext.java         |   5 -
 .../authorization/AuthorizerFactoryBean.java    |   8 +-
 .../main/resources/nifi-authorizer-context.xml  |   1 -
 .../nifi-framework/nifi-file-authorizer/pom.xml |   4 +
 .../nifi/authorization/FileAuthorizer.java      | 451 ++++++++++++++++---
 .../org/apache/nifi/authorization/Role.java     |  30 ++
 .../nifi/authorization/RoleAccessPolicy.java    |  99 ++++
 .../nifi/authorization/FileAuthorizerTest.java  | 282 +++++++++++-
 .../resources/authorized-users-multirole.xml    |  21 +
 .../src/test/resources/authorized-users.xml     |  35 ++
 .../src/test/resources/flow.xml.gz              | Bin 0 -> 566 bytes
 .../StandardAuthorizerConfigurationContext.java |   9 +-
 .../authorization/resource/ResourceFactory.java | 370 +++++++++++++--
 .../authorization/resource/ResourceType.java    |  23 +-
 .../src/main/resources/conf/authorizers.xml     |   1 +
 15 files changed, 1211 insertions(+), 128 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizerConfigurationContext.java
----------------------------------------------------------------------
diff --git 
a/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizerConfigurationContext.java
 
b/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizerConfigurationContext.java
index 20cb69e..3721ab4 100644
--- 
a/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizerConfigurationContext.java
+++ 
b/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizerConfigurationContext.java
@@ -31,11 +31,6 @@ public interface AuthorizerConfigurationContext {
     String getIdentifier();
 
     /**
-     * @return the id of the root process group
-     */
-    String getRootGroupId();
-
-    /**
      * Retrieves all properties the component currently understands regardless
      * of whether a value has been set for them or not. If no value is present
      * then its value is null and thus any registered default for the property

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
index e4d7318..d061fe1 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
@@ -23,7 +23,6 @@ import 
org.apache.nifi.authorization.exception.AuthorizerCreationException;
 import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
 import org.apache.nifi.authorization.generated.Authorizers;
 import org.apache.nifi.authorization.generated.Property;
-import org.apache.nifi.controller.FlowController;
 import org.apache.nifi.nar.ExtensionManager;
 import org.apache.nifi.nar.NarCloseable;
 import org.apache.nifi.util.NiFiProperties;
@@ -72,13 +71,8 @@ public class AuthorizerFactoryBean implements FactoryBean, 
DisposableBean, Autho
 
     private Authorizer authorizer;
     private NiFiProperties properties;
-    private FlowController flowController;
     private final Map<String, Authorizer> authorizers = new HashMap<>();
 
-    public void setFlowController(FlowController flowController) {
-        this.flowController = flowController;
-    }
-
     @Override
     public Authorizer getAuthorizer(String identifier) {
         return authorizers.get(identifier);
@@ -195,7 +189,7 @@ public class AuthorizerFactoryBean implements FactoryBean, 
DisposableBean, Autho
             authorizerProperties.put(property.getName(), property.getValue());
         }
 
-        return new 
StandardAuthorizerConfigurationContext(authorizer.getIdentifier(), 
flowController.getRootGroupId(), authorizerProperties);
+        return new 
StandardAuthorizerConfigurationContext(authorizer.getIdentifier(), 
authorizerProperties);
     }
 
     private void performMethodInjection(final Authorizer instance, final Class 
authorizerClass) throws IllegalAccessException, IllegalArgumentException, 
InvocationTargetException {

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/resources/nifi-authorizer-context.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/resources/nifi-authorizer-context.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/resources/nifi-authorizer-context.xml
index b95db11..71bf684 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/resources/nifi-authorizer-context.xml
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/resources/nifi-authorizer-context.xml
@@ -21,7 +21,6 @@
     <!-- user/entity authorizer -->
     <bean id="authorizer" 
class="org.apache.nifi.authorization.AuthorizerFactoryBean">
         <property name="properties" ref="nifiProperties"/>
-        <property name="flowController" ref="flowController"/>
     </bean>
 
 </beans>

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/pom.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/pom.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/pom.xml
index 4f97220..c7fbb2c 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/pom.xml
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/pom.xml
@@ -94,6 +94,10 @@
             <artifactId>nifi-framework-authorization</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-framework-core</artifactId>
+        </dependency>
+        <dependency>
             <groupId>commons-codec</groupId>
             <artifactId>commons-codec</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
index ca99e09..20a43c3 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
@@ -25,11 +25,15 @@ import org.apache.nifi.authorization.file.generated.Groups;
 import org.apache.nifi.authorization.file.generated.Policies;
 import org.apache.nifi.authorization.file.generated.Policy;
 import org.apache.nifi.authorization.file.generated.Users;
+import org.apache.nifi.authorization.resource.ResourceType;
 import org.apache.nifi.components.PropertyValue;
 import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.util.file.FileUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
 
 import javax.xml.XMLConstants;
 import javax.xml.bind.JAXBContext;
@@ -37,18 +41,29 @@ import javax.xml.bind.JAXBElement;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.stream.StreamSource;
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.zip.GZIPInputStream;
 
 /**
  * Provides identity checks and grants authorities.
@@ -56,30 +71,47 @@ import java.util.concurrent.atomic.AtomicReference;
 public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
 
     private static final Logger logger = 
LoggerFactory.getLogger(FileAuthorizer.class);
-    private static final String USERS_XSD = "/authorizations.xsd";
-    private static final String JAXB_GENERATED_PATH = 
"org.apache.nifi.authorization.file.generated";
-    private static final JAXBContext JAXB_CONTEXT = initializeJaxbContext();
 
-    static final String READ_CODE = "R";
-    static final String WRITE_CODE = "W";
+    private static final String AUTHORIZATIONS_XSD = "/authorizations.xsd";
+    private static final String JAXB_AUTHORIZATIONS_PATH = 
"org.apache.nifi.authorization.file.generated";
+
+    private static final String USERS_XSD = "/users.xsd";
+    private static final String JAXB_USERS_PATH = 
"org.apache.nifi.user.generated";
+
+    private static final String FLOW_XSD = "/FlowConfiguration.xsd";
+
+    private static final JAXBContext JAXB_AUTHORIZATIONS_CONTEXT = 
initializeJaxbContext(JAXB_AUTHORIZATIONS_PATH);
+    private static final JAXBContext JAXB_USERS_CONTEXT = 
initializeJaxbContext(JAXB_USERS_PATH);
 
     /**
      * Load the JAXBContext.
      */
-    private static JAXBContext initializeJaxbContext() {
+    private static JAXBContext initializeJaxbContext(final String contextPath) 
{
         try {
-            return JAXBContext.newInstance(JAXB_GENERATED_PATH, 
FileAuthorizer.class.getClassLoader());
+            return JAXBContext.newInstance(contextPath, 
FileAuthorizer.class.getClassLoader());
         } catch (JAXBException e) {
             throw new RuntimeException("Unable to create JAXBContext.");
         }
     }
 
-    private Schema schema;
+    static final String READ_CODE = "R";
+    static final String WRITE_CODE = "W";
+
+    static final String PROP_AUTHORIZATIONS_FILE = "Authorizations File";
+    static final String PROP_INITIAL_ADMIN_IDENTITY = "Initial Admin Identity";
+    static final String PROP_LEGACY_AUTHORIZED_USERS_FILE = "Legacy Authorized 
Users File";
+    static final String PROP_ROOT_GROUP_ID = "Root Group ID";
+
+    private Schema flowSchema;
+    private Schema usersSchema;
+    private Schema authorizationsSchema;
     private SchemaFactory schemaFactory;
     private NiFiProperties properties;
     private File authorizationsFile;
     private File restoreAuthorizationsFile;
     private String rootGroupId;
+    private String initialAdminIdentity;
+    private String legacyAuthorizedUsersFile;
 
     private final AtomicReference<AuthorizationsHolder> authorizationsHolder = 
new AtomicReference<>();
 
@@ -87,7 +119,9 @@ public class FileAuthorizer extends 
AbstractPolicyBasedAuthorizer {
     public void initialize(final AuthorizerInitializationContext 
initializationContext) throws AuthorizerCreationException {
         try {
             schemaFactory = 
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-            schema = 
schemaFactory.newSchema(FileAuthorizer.class.getResource(USERS_XSD));
+            authorizationsSchema = 
schemaFactory.newSchema(FileAuthorizer.class.getResource(AUTHORIZATIONS_XSD));
+            usersSchema = 
schemaFactory.newSchema(FileAuthorizer.class.getResource(USERS_XSD));
+            flowSchema = 
schemaFactory.newSchema(FileAuthorizer.class.getResource(FLOW_XSD));
         } catch (Exception e) {
             throw new AuthorizerCreationException(e);
         }
@@ -96,7 +130,7 @@ public class FileAuthorizer extends 
AbstractPolicyBasedAuthorizer {
     @Override
     public void onConfigured(final AuthorizerConfigurationContext 
configurationContext) throws AuthorizerCreationException {
         try {
-            final PropertyValue authorizationsPath = 
configurationContext.getProperty("Authorizations File");
+            final PropertyValue authorizationsPath = 
configurationContext.getProperty(PROP_AUTHORIZATIONS_FILE);
             if (StringUtils.isBlank(authorizationsPath.getValue())) {
                 throw new AuthorizerCreationException("The authorizations file 
must be specified.");
             }
@@ -132,11 +166,17 @@ public class FileAuthorizer extends 
AbstractPolicyBasedAuthorizer {
                 }
             }
 
-            final PropertyValue initialAdminIdentityProp = 
configurationContext.getProperty("Initial Admin Identity");
-            final String initialAdminIdentity = initialAdminIdentityProp == 
null ? null : initialAdminIdentityProp.getValue();
+            final PropertyValue initialAdminIdentityProp = 
configurationContext.getProperty(PROP_INITIAL_ADMIN_IDENTITY);
+            initialAdminIdentity = initialAdminIdentityProp == null ? null : 
initialAdminIdentityProp.getValue();
+
+            final PropertyValue legacyAuthorizedUsersProp = 
configurationContext.getProperty(PROP_LEGACY_AUTHORIZED_USERS_FILE);
+            legacyAuthorizedUsersFile = legacyAuthorizedUsersProp == null ? 
null : legacyAuthorizedUsersProp.getValue();
+
+            // try to extract the root group id from the flow configuration 
file specified in nifi.properties
+            rootGroupId = getRootGroupId();
 
             // load the authorizations
-            load(initialAdminIdentity);
+            load();
 
             // if we've copied the authorizations file to a restore directory 
synchronize it
             if (restoreAuthorizationsFile != null) {
@@ -145,24 +185,82 @@ public class FileAuthorizer extends 
AbstractPolicyBasedAuthorizer {
 
             logger.info(String.format("Authorizations file loaded at %s", new 
Date().toString()));
 
-            this.rootGroupId = configurationContext.getRootGroupId();
-
         } catch (IOException | AuthorizerCreationException | JAXBException | 
IllegalStateException e) {
             throw new AuthorizerCreationException(e);
         }
     }
 
     /**
+     * Extracts the root group id from the flow configuration file provided in 
nifi.properties.
+     *
+     * @return the root group id, or null if the files doesn't exist, was 
empty, or could not be parsed
+     */
+    private String getRootGroupId() {
+        final File flowFile = properties.getFlowConfigurationFile();
+        if (flowFile == null) {
+            logger.debug("Flow Configuration file was null");
+            return null;
+        }
+
+        // if the flow doesn't exist or is 0 bytes, then return null
+        final Path flowPath = flowFile.toPath();
+        try {
+            if (!Files.exists(flowPath) || Files.size(flowPath) == 0) {
+                logger.debug("Flow Configuration does not exist or was empty");
+                return null;
+            }
+        } catch (IOException e) {
+            logger.debug("An error occurred determining the size of the Flow 
Configuration file");
+            return null;
+        }
+
+        // otherwise create the appropriate input streams to read the file
+        try (final InputStream in = Files.newInputStream(flowPath, 
StandardOpenOption.READ);
+             final InputStream gzipIn = new GZIPInputStream(in)) {
+
+            // create validating document builder
+            final DocumentBuilderFactory docFactory = 
DocumentBuilderFactory.newInstance();
+            docFactory.setNamespaceAware(true);
+            docFactory.setSchema(flowSchema);
+
+            // parse the flow
+            final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+            final Document document = docBuilder.parse(gzipIn);
+
+            // extract the root group id
+            final Element rootElement = document.getDocumentElement();
+
+            final Element rootGroupElement = (Element) 
rootElement.getElementsByTagName("rootGroup").item(0);
+            if (rootGroupElement == null) {
+                logger.debug("rootGroup element not found in Flow 
Configuration file");
+                return null;
+            }
+
+            final Element rootGroupIdElement = (Element) 
rootGroupElement.getElementsByTagName("id").item(0);
+            if (rootGroupIdElement == null) {
+                logger.debug("id element not found under rootGroup in Flow 
Configuration file");
+                return null;
+            }
+
+            return rootGroupIdElement.getTextContent();
+
+        } catch (final SAXException | ParserConfigurationException | 
IOException ex) {
+            logger.error("Unable to find root group id in {} due to {}", new 
Object[] { flowPath.toAbsolutePath(), ex });
+            return null;
+        }
+    }
+
+    /**
      * Loads the authorizations file and populates the AuthorizationsHolder, 
only called during start-up.
      *
      * @throws JAXBException            Unable to reload the authorized users 
file
      * @throws IOException              Unable to sync file with restore
      * @throws IllegalStateException    Unable to sync file with restore
      */
-    private synchronized void load(final String initialAdminIdentity) throws 
JAXBException, IOException, IllegalStateException {
+    private synchronized void load() throws JAXBException, IOException, 
IllegalStateException {
         // attempt to unmarshal
-        final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
-        unmarshaller.setSchema(schema);
+        final Unmarshaller unmarshaller = 
JAXB_AUTHORIZATIONS_CONTEXT.createUnmarshaller();
+        unmarshaller.setSchema(authorizationsSchema);
         final JAXBElement<Authorizations> element = unmarshaller.unmarshal(new 
StreamSource(authorizationsFile), Authorizations.class);
 
         final Authorizations authorizations = element.getValue();
@@ -178,11 +276,24 @@ public class FileAuthorizer extends 
AbstractPolicyBasedAuthorizer {
         }
 
         final AuthorizationsHolder authorizationsHolder = new 
AuthorizationsHolder(authorizations);
+        final boolean emptyAuthorizations = 
authorizationsHolder.getAllUsers().isEmpty() && 
authorizationsHolder.getAllPolicies().isEmpty();
         final boolean hasInitialAdminIdentity = (initialAdminIdentity != null 
&& !StringUtils.isBlank(initialAdminIdentity));
+        final boolean hasLegacyAuthorizedUsers = (legacyAuthorizedUsersFile != 
null && !StringUtils.isBlank(legacyAuthorizedUsersFile));
+
+        // if we are starting fresh then we might need to populate an initial 
admin or convert legacy users
+        if (emptyAuthorizations) {
+
+            if (hasInitialAdminIdentity && hasLegacyAuthorizedUsers) {
+                throw new AuthorizerCreationException("Cannot provide an 
Initial Admin Identity and a Legacy Authorized Users File");
+            } else if (hasInitialAdminIdentity) {
+                logger.debug("Populating authorizations for Initial Admin: " + 
initialAdminIdentity);
+                populateInitialAdmin(authorizations);
+            } else if (hasLegacyAuthorizedUsers) {
+                logger.debug("Converting " + legacyAuthorizedUsersFile + " to 
new authorizations model");
+                convertLegacyAuthorizedUsers(authorizations);
+            }
 
-        // if an initial admin was provided and there are no users or policies 
then automatically create the admin user & policies
-        if (hasInitialAdminIdentity && 
authorizationsHolder.getAllUsers().isEmpty() && 
authorizationsHolder.getAllPolicies().isEmpty()) {
-            populateInitialAdmin(authorizations, initialAdminIdentity);
+            // save any changes that were made and repopulate the holder
             saveAndRefreshHolder(authorizations);
         } else {
             this.authorizationsHolder.set(authorizationsHolder);
@@ -191,60 +302,298 @@ public class FileAuthorizer extends 
AbstractPolicyBasedAuthorizer {
 
     /**
      *  Creates the initial admin user and policies for access the flow and 
managing users and policies.
-     *
-     * @param adminIdentity the identity of the admin user
      */
-    private void populateInitialAdmin(final Authorizations authorizations, 
final String adminIdentity) {
+    private void populateInitialAdmin(final Authorizations authorizations) {
         // generate an identifier and add a User with the given identifier and 
identity
-        final UUID adminIdentifier = 
UUID.nameUUIDFromBytes(adminIdentity.getBytes(StandardCharsets.UTF_8));
-        final User adminUser = new 
User.Builder().identifier(adminIdentifier.toString()).identity(adminIdentity).build();
+        final UUID adminIdentifier = 
UUID.nameUUIDFromBytes(initialAdminIdentity.getBytes(StandardCharsets.UTF_8));
+        final User adminUser = new 
User.Builder().identifier(adminIdentifier.toString()).identity(initialAdminIdentity).build();
 
         final org.apache.nifi.authorization.file.generated.User jaxbAdminUser 
= createJAXBUser(adminUser);
         authorizations.getUsers().getUser().add(jaxbAdminUser);
 
         // grant the user read access to the /flow resource
-        final AccessPolicy flowPolicy = createInitialAdminPolicy("/flow", 
adminUser.getIdentifier(), RequestAction.READ);
-        final Policy jaxbFlowPolicy = createJAXBPolicy(flowPolicy);
-        authorizations.getPolicies().getPolicy().add(jaxbFlowPolicy);
+        addAccessPolicy(authorizations, ResourceType.Flow.getValue(), 
adminUser.getIdentifier(), READ_CODE);
+
+        // grant the user read access to the root process group resource
+        if (rootGroupId != null) {
+            addAccessPolicy(authorizations, 
ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, 
adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
+        }
 
         // grant the user read/write access to the /users resource
-        final AccessPolicy usersPolicy = createInitialAdminPolicy("/users", 
adminUser.getIdentifier(), RequestAction.READ, RequestAction.WRITE);
-        final Policy jaxbUsersPolicy = createJAXBPolicy(usersPolicy);
-        authorizations.getPolicies().getPolicy().add(jaxbUsersPolicy);
+        addAccessPolicy(authorizations, ResourceType.User.getValue(), 
adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
 
         // grant the user read/write access to the /groups resource
-        final AccessPolicy groupsPolicy = createInitialAdminPolicy("/groups", 
adminUser.getIdentifier(), RequestAction.READ, RequestAction.WRITE);
-        final Policy jaxbGroupsPolicy = createJAXBPolicy(groupsPolicy);
-        authorizations.getPolicies().getPolicy().add(jaxbGroupsPolicy);
+        addAccessPolicy(authorizations, ResourceType.Group.getValue(), 
adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
 
         // grant the user read/write access to the /policies resource
-        final AccessPolicy policiesPolicy = 
createInitialAdminPolicy("/policies", adminUser.getIdentifier(), 
RequestAction.READ, RequestAction.WRITE);
-        final Policy jaxbPoliciesPolicy = createJAXBPolicy(policiesPolicy);
-        authorizations.getPolicies().getPolicy().add(jaxbPoliciesPolicy);
+        addAccessPolicy(authorizations, ResourceType.Policy.getValue(), 
adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
     }
 
     /**
-     * Creates an AccessPolicy based on the given parameters, generating an 
identifier from the resource and admin identity.
+     * Unmarshalls an existing authorized-users.xml and converts the object 
model to the new model.
      *
+     * @param authorizations the current Authorizations instance that users, 
groups, and policies will be added to
+     * @throws AuthorizerCreationException if the legacy authorized users file 
that was provided does not exist
+     * @throws JAXBException if the legacy authorized users file that was 
provided could not be unmarshalled
+     */
+    private void convertLegacyAuthorizedUsers(final Authorizations 
authorizations) throws AuthorizerCreationException, JAXBException {
+        final File authorizedUsersFile = new File(legacyAuthorizedUsersFile);
+        if (!authorizedUsersFile.exists()) {
+            throw new AuthorizerCreationException("Legacy Authorized Users 
File '" + legacyAuthorizedUsersFile + "' does not exists");
+        }
+
+        final Unmarshaller unmarshaller = 
JAXB_USERS_CONTEXT.createUnmarshaller();
+        unmarshaller.setSchema(usersSchema);
+
+        final JAXBElement<org.apache.nifi.user.generated.Users> element = 
unmarshaller.unmarshal(
+                new StreamSource(authorizedUsersFile), 
org.apache.nifi.user.generated.Users.class);
+
+        final org.apache.nifi.user.generated.Users users = element.getValue();
+        if (users.getUser().isEmpty()) {
+            logger.info("Legacy Authorized Users File contained no users, 
nothing to convert");
+            return;
+        }
+
+        // get all the user DNs into a list
+        List<String> userIdentities = new ArrayList<>();
+        for (org.apache.nifi.user.generated.User legacyUser : users.getUser()) 
{
+            userIdentities.add(legacyUser.getDn());
+        }
+
+        // sort the list and pull out the first identity
+        Collections.sort(userIdentities);
+        final String seedIdentity = userIdentities.get(0);
+
+        // create mapping from Role to access policies
+        final Map<Role,Set<RoleAccessPolicy>> roleAccessPolicies = 
RoleAccessPolicy.getMappings(rootGroupId);
+
+        final List<Policy> readPolicies = new ArrayList<>();
+        final List<Policy> readWritePolicies = new ArrayList<>();
+
+        for (org.apache.nifi.user.generated.User legacyUser : users.getUser()) 
{
+            // create the identifier of the new user based on the DN
+            String legacyUserDn = legacyUser.getDn();
+            String userIdentifier = 
UUID.nameUUIDFromBytes(legacyUserDn.getBytes(StandardCharsets.UTF_8)).toString();
+
+            // create the new User and add it to the list of users
+            org.apache.nifi.authorization.file.generated.User user = new 
org.apache.nifi.authorization.file.generated.User();
+            user.setIdentifier(userIdentifier);
+            user.setIdentity(legacyUserDn);
+            authorizations.getUsers().getUser().add(user);
+
+            // if there was a group name find or create the group and add the 
user to it
+            org.apache.nifi.authorization.file.generated.Group group = 
getOrCreateGroup(authorizations, legacyUser.getGroup());
+            if (group != null) {
+                org.apache.nifi.authorization.file.generated.User.Group 
userGroup = new org.apache.nifi.authorization.file.generated.User.Group();
+                userGroup.setIdentifier(group.getIdentifier());
+                user.getGroup().add(userGroup);
+            }
+
+            // create policies based on the given role
+            for (org.apache.nifi.user.generated.Role jaxbRole : 
legacyUser.getRole()) {
+                Role role = Role.valueOf(jaxbRole.getName());
+                Set<RoleAccessPolicy> policies = roleAccessPolicies.get(role);
+
+                for (RoleAccessPolicy roleAccessPolicy : policies) {
+                    // determine if we should use the read policies or 
read-write policies
+                    List<Policy> searchPolicies = 
roleAccessPolicy.getActions().equals(RoleAccessPolicy.READ_ACTION)
+                            ? readPolicies : readWritePolicies;
+
+                    // get the matching policy, or create a new one
+                    Policy policy = getOrCreatePolicy(
+                            searchPolicies,
+                            seedIdentity,
+                            roleAccessPolicy.getResource(),
+                            roleAccessPolicy.getActions());
+
+                    // determine if the user already exists in the policy
+                    boolean userExists = false;
+                    for (Policy.User policyUser : policy.getUser()) {
+                        if (policyUser.getIdentifier().equals(userIdentifier)) 
{
+                            userExists = true;
+                            break;
+                        }
+                    }
+
+                    // add the user to the policy if doesn't already exist
+                    if (!userExists) {
+                        Policy.User policyUser = new Policy.User();
+                        policyUser.setIdentifier(userIdentifier);
+                        policy.getUser().add(policyUser);
+                    }
+                }
+            }
+
+        }
+
+        // merge the policies and add the result to the overall authorizations 
instance
+        final List<Policy> mergedPolicies = merge(readPolicies, 
readWritePolicies);
+        authorizations.getPolicies().getPolicy().addAll(mergedPolicies);
+    }
+
+    /**
+     * Merges the provided read and read-write policies. Any users that are in 
a read policy and also in a read-write
+     * policy for the same resource will be removed from the read policy. If 
users are still left in the read policy
+     * after checking each user, then the read policy will still be included 
in the merged list.
+     *
+     * @param readPolicies the read policies
+     * @param readWritePolicies the read-write policies
+     * @return the merged list of policies
+     */
+    private List<Policy> merge(List<Policy> readPolicies, List<Policy> 
readWritePolicies) {
+        final List<Policy> mergedPolicies = new ArrayList<>(readWritePolicies);
+
+        logger.debug("Merging {} read policies and {} read-write policies",
+                new Object[] {readPolicies.size(), readWritePolicies.size()});
+
+        for (Policy readPolicy : readPolicies) {
+            logger.debug("Processing read policy {} for resource {} with 
actions {}",
+                    new Object[] {readPolicy.getIdentifier(), 
readPolicy.getResource(), readPolicy.getAction()});
+
+            // try to find a matching read-write policy for the same resource
+            Policy foundReadWritePolicy = null;
+            for (Policy readWritePolicy : readWritePolicies) {
+                if 
(readWritePolicy.getResource().equals(readPolicy.getResource())) {
+                    foundReadWritePolicy = readWritePolicy;
+                    break;
+                }
+            }
+
+            // if we didn't find a match then we just add the current read 
policy to the merged list
+            if (foundReadWritePolicy == null) {
+                logger.debug("no matching write policy found, adding read 
policy {} to merged policies",
+                        new Object[] {readPolicy.getIdentifier()});
+                mergedPolicies.add(readPolicy);
+            } else {
+                // check each user from the read policy
+                Iterator<Policy.User> userIter = 
readPolicy.getUser().iterator();
+                while (userIter.hasNext()) {
+                    Policy.User readUser = userIter.next();
+
+                    // determine if the user from the read policy exists in 
the read-write policy
+                    boolean userInReadWrite = false;
+                    for (Policy.User readWriteUser : 
foundReadWritePolicy.getUser()) {
+                        if 
(readWriteUser.getIdentifier().equals(readUser.getIdentifier())) {
+                            userInReadWrite = true;
+                            break;
+                        }
+                    }
+
+                    // if the user was in the read-write policy, remove them 
from read policy
+                    if (userInReadWrite) {
+                        logger.debug("Removing user {} from read policy {}", 
new Object[] {readUser.getIdentifier(), readPolicy.getIdentifier()});
+                        userIter.remove();
+                    }
+                }
+
+                // after checking all users, see if any are still left in the 
read policy
+                // if there are still some users, then add the read policy to 
the merged list
+                if (readPolicy.getUser().size() > 0) {
+                    logger.debug("Read policy still has {} users, adding read 
policy {} to merged list",
+                            new Object[] {readPolicy.getUser().size(), 
readPolicy.getIdentifier()});
+                    mergedPolicies.add(readPolicy);
+                }
+            }
+        }
+
+        return mergedPolicies;
+    }
+
+    /**
+     * Finds the Group with the given name, or creates a new one and adds it 
to Authorizations.
+     *
+     * @param authorizations the Authorizations reference
+     * @param groupName the name of the group to look for
+     * @return the Group from Authorizations with the given name, or a new 
instance
+     */
+    private org.apache.nifi.authorization.file.generated.Group 
getOrCreateGroup(final Authorizations authorizations, final String groupName) {
+        if (StringUtils.isBlank(groupName)) {
+            return null;
+        }
+
+        org.apache.nifi.authorization.file.generated.Group foundGroup = null;
+        for (org.apache.nifi.authorization.file.generated.Group group : 
authorizations.getGroups().getGroup()) {
+            if (group.getName().equals(groupName)) {
+                foundGroup = group;
+                break;
+            }
+        }
+
+        if (foundGroup == null) {
+            UUID newGroupIdentifier = 
UUID.nameUUIDFromBytes(groupName.getBytes(StandardCharsets.UTF_8));
+            foundGroup = new 
org.apache.nifi.authorization.file.generated.Group();
+            foundGroup.setIdentifier(newGroupIdentifier.toString());
+            foundGroup.setName(groupName);
+            authorizations.getGroups().getGroup().add(foundGroup);
+        }
+
+        return foundGroup;
+    }
+
+    /**
+     * Finds the Policy matching the resource and action, or creates a new one 
and adds it to the list of policies.
+     *
+     * @param policies the policies to search through
+     * @param seedIdentity the seedIdentity to use when creating identifiers 
for new policies
      * @param resource the resource for the policy
-     * @param adminIdentity the identity of the admin user to add to the policy
+     * @param action the action string for the police (R or RW)
+     * @return the matching policy or a new policy
+     */
+    private Policy getOrCreatePolicy(final List<Policy> policies, final String 
seedIdentity, final String resource, final String action) {
+        Policy foundPolicy = null;
+
+        // try to find a policy with the same resource and actions
+        for (Policy policy : policies) {
+            if (policy.getResource().equals(resource) && 
policy.getAction().equals(action)) {
+                foundPolicy = policy;
+                break;
+            }
+        }
+
+        // if a matching policy wasn't found then create one
+        if (foundPolicy == null) {
+            final String uuidSeed = resource + action + seedIdentity;
+            final UUID policyIdentifier = 
UUID.nameUUIDFromBytes(uuidSeed.getBytes(StandardCharsets.UTF_8));
+
+            foundPolicy = new Policy();
+            foundPolicy.setIdentifier(policyIdentifier.toString());
+            foundPolicy.setResource(resource);
+            foundPolicy.setAction(action);
+
+            policies.add(foundPolicy);
+        }
+
+        return foundPolicy;
+    }
+
+    /**
+     * Creates and adds an access policy for the given resource, identity, and 
actions.
+     *
+     * @param authorizations the Authorizations instance to add the policy to
+     * @param resource the resource for the policy
+     * @param identity the identity for the policy
      * @param actions the actions for the policy
-     * @return the AccessPolicy based on the given parameters
      */
-    private AccessPolicy createInitialAdminPolicy(final String resource, final 
String adminIdentity, final RequestAction ... actions) {
-        final String uuidSeed = resource + adminIdentity;
-        final UUID flowPolicyIdentifier = 
UUID.nameUUIDFromBytes(uuidSeed.getBytes(StandardCharsets.UTF_8));
+    private void addAccessPolicy(final Authorizations authorizations, final 
String resource, final String identity, final String actions) {
+        final String uuidSeed = resource + identity;
+        final UUID policyIdentifier = 
UUID.nameUUIDFromBytes(uuidSeed.getBytes(StandardCharsets.UTF_8));
 
         final AccessPolicy.Builder builder = new AccessPolicy.Builder()
-                .identifier(flowPolicyIdentifier.toString())
+                .identifier(policyIdentifier.toString())
                 .resource(resource)
-                .addUser(adminIdentity);
+                .addUser(identity);
+
+        if (actions.contains(READ_CODE)) {
+            builder.addAction(RequestAction.READ);
+        }
 
-        for (RequestAction action : actions) {
-            builder.addAction(action);
+        if (actions.contains(WRITE_CODE)) {
+            builder.addAction(RequestAction.WRITE);
         }
 
-        return builder.build();
+        final AccessPolicy accessPolicy = builder.build();
+        final Policy jaxbPolicy = createJAXBPolicy(accessPolicy);
+        authorizations.getPolicies().getPolicy().add(jaxbPolicy);
     }
 
     /**
@@ -258,8 +607,8 @@ public class FileAuthorizer extends 
AbstractPolicyBasedAuthorizer {
      */
     private synchronized void saveAndRefreshHolder(final Authorizations 
authorizations) throws AuthorizationAccessException {
         try {
-            final Marshaller marshaller = JAXB_CONTEXT.createMarshaller();
-            marshaller.setSchema(schema);
+            final Marshaller marshaller = 
JAXB_AUTHORIZATIONS_CONTEXT.createMarshaller();
+            marshaller.setSchema(authorizationsSchema);
             marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
             marshaller.marshal(authorizations, authorizationsFile);
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/Role.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/Role.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/Role.java
new file mode 100644
index 0000000..0f7b740
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/Role.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * Legacy Roles prior to the new authorization model.
+ */
+public enum Role {
+    ROLE_MONITOR,
+    ROLE_PROVENANCE,
+    ROLE_DFM,
+    ROLE_ADMIN,
+    ROLE_PROXY,
+    ROLE_NIFI;
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java
new file mode 100644
index 0000000..6757402
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java
@@ -0,0 +1,99 @@
+/*
+ * 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.authorization.resource.ResourceType;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Defines the mapping from legacy roles to access policies.
+ */
+public final class RoleAccessPolicy {
+
+    static final String READ_ACTION = "R";
+    static final String READ_WRITE_ACTION = "RW";
+
+    private final String resource;
+    private final String actions;
+
+    private RoleAccessPolicy(final String resource, final String actions) {
+        this.resource = resource;
+        this.actions = actions;
+    }
+
+    public String getResource() {
+        return resource;
+    }
+
+    public String getActions() {
+        return actions;
+    }
+
+    public static Map<Role,Set<RoleAccessPolicy>> getMappings(final String 
rootGroupId) {
+        final Map<Role,Set<RoleAccessPolicy>> roleAccessPolicies = new 
HashMap<>();
+
+        final Set<RoleAccessPolicy> monitorPolicies = new HashSet<>();
+        monitorPolicies.add(new RoleAccessPolicy(ResourceType.Flow.getValue(), 
READ_ACTION));
+        monitorPolicies.add(new 
RoleAccessPolicy(ResourceType.Controller.getValue(), READ_ACTION));
+        monitorPolicies.add(new 
RoleAccessPolicy(ResourceType.System.getValue(), READ_ACTION));
+        if (rootGroupId != null) {
+            monitorPolicies.add(new 
RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, 
READ_ACTION));
+        }
+        roleAccessPolicies.put(Role.ROLE_MONITOR, 
Collections.unmodifiableSet(monitorPolicies));
+
+        final Set<RoleAccessPolicy> provenancePolicies = new HashSet<>();
+        provenancePolicies.add(new 
RoleAccessPolicy(ResourceType.Provenance.getValue(), READ_ACTION));
+        roleAccessPolicies.put(Role.ROLE_PROVENANCE, 
Collections.unmodifiableSet(provenancePolicies));
+
+        final Set<RoleAccessPolicy> dfmPolicies = new HashSet<>();
+        dfmPolicies.add(new RoleAccessPolicy(ResourceType.Flow.getValue(), 
READ_ACTION));
+        dfmPolicies.add(new 
RoleAccessPolicy(ResourceType.Controller.getValue(), READ_WRITE_ACTION));
+        dfmPolicies.add(new RoleAccessPolicy(ResourceType.System.getValue(), 
READ_ACTION));
+        if (rootGroupId != null) {
+            dfmPolicies.add(new 
RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, 
READ_WRITE_ACTION));
+        }
+        roleAccessPolicies.put(Role.ROLE_DFM, 
Collections.unmodifiableSet(dfmPolicies));
+
+        final Set<RoleAccessPolicy> adminPolicies = new HashSet<>();
+        adminPolicies.add(new RoleAccessPolicy(ResourceType.Flow.getValue(), 
READ_ACTION));
+        adminPolicies.add(new 
RoleAccessPolicy(ResourceType.Controller.getValue(), READ_ACTION));
+        if (rootGroupId != null) {
+            adminPolicies.add(new 
RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, 
READ_ACTION));
+        }
+        adminPolicies.add(new RoleAccessPolicy(ResourceType.User.getValue(), 
READ_WRITE_ACTION));
+        adminPolicies.add(new RoleAccessPolicy(ResourceType.Group.getValue(), 
READ_WRITE_ACTION));
+        adminPolicies.add(new RoleAccessPolicy(ResourceType.Policy.getValue(), 
READ_WRITE_ACTION));
+        roleAccessPolicies.put(Role.ROLE_ADMIN, 
Collections.unmodifiableSet(adminPolicies));
+
+        final Set<RoleAccessPolicy> proxyPolicies = new HashSet<>();
+        proxyPolicies.add(new RoleAccessPolicy(ResourceType.Proxy.getValue(), 
READ_WRITE_ACTION));
+        roleAccessPolicies.put(Role.ROLE_PROXY, 
Collections.unmodifiableSet(proxyPolicies));
+
+        final Set<RoleAccessPolicy> nifiPolicies = new HashSet<>();
+        nifiPolicies.add(new 
RoleAccessPolicy(ResourceType.Controller.getValue(), READ_ACTION));
+        nifiPolicies.add(new 
RoleAccessPolicy(ResourceType.SiteToSite.getValue(), READ_WRITE_ACTION));
+        roleAccessPolicies.put(Role.ROLE_NIFI, 
Collections.unmodifiableSet(nifiPolicies));
+
+        return roleAccessPolicies;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
index 0822b60..6d18b4b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
@@ -20,6 +20,7 @@ import 
org.apache.nifi.attribute.expression.language.StandardPropertyValue;
 import org.apache.nifi.authorization.AuthorizationResult.Result;
 import org.apache.nifi.authorization.exception.AuthorizerCreationException;
 import org.apache.nifi.authorization.resource.ResourceFactory;
+import org.apache.nifi.authorization.resource.ResourceType;
 import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.util.file.FileUtils;
 import org.junit.After;
@@ -31,6 +32,9 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
@@ -97,17 +101,14 @@ public class FileAuthorizerTest {
             "  </policies>" +
             "</authorizations>";
 
-    private static final String UPDATED_AUTHORIZATIONS =
-        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
-        + "<resources>"
-            + "<resource identifier=\"/flow\">"
-                + "<authorization identity=\"user-1\" action=\"RW\"/>"
-            + "</resource>"
-        + "</resources>";
+    // This is the root group id from the flow.xml.gz in src/test/resources
+    private static final String ROOT_GROUP_ID = 
"e530e14c-adcf-41c2-b5d6-d9a59ba8765c";
 
+    private NiFiProperties properties;
     private FileAuthorizer authorizer;
     private File primary;
     private File restore;
+    private File flow;
 
     private AuthorizerConfigurationContext configurationContext;
 
@@ -121,8 +122,12 @@ public class FileAuthorizerTest {
         restore = new File("target/restore/authorizations.xml");
         FileUtils.ensureDirectoryExistAndCanAccess(restore.getParentFile());
 
-        final NiFiProperties properties = mock(NiFiProperties.class);
+        flow = new File("src/test/resources/flow.xml.gz");
+        FileUtils.ensureDirectoryExistAndCanAccess(flow.getParentFile());
+
+        properties = mock(NiFiProperties.class);
         
when(properties.getRestoreDirectory()).thenReturn(restore.getParentFile());
+        when(properties.getFlowConfigurationFile()).thenReturn(flow);
 
         configurationContext = mock(AuthorizerConfigurationContext.class);
         when(configurationContext.getProperty(Mockito.eq("Authorizations 
File"))).thenReturn(new StandardPropertyValue(primary.getPath(), null));
@@ -139,10 +144,225 @@ public class FileAuthorizerTest {
     }
 
     @Test
+    public void 
testOnConfiguredWhenLegacyUsersFileProvidedWithOverlappingRoles() throws 
Exception {
+        
when(configurationContext.getProperty(Mockito.eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE)))
+                .thenReturn(new 
StandardPropertyValue("src/test/resources/authorized-users-multirole.xml", 
null));
+
+        writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
+        authorizer.onConfigured(configurationContext);
+
+        final Set<User> users = authorizer.getUsers();
+        assertEquals(1, users.size());
+
+        // the user has monitor and DFM, but we should only end up with one 
policy per resource
+        // since DFM has RW to all the same resources that monitor has R
+        UsersAndAccessPolicies usersAndAccessPolicies = 
authorizer.getUsersAndAccessPolicies();
+        assertEquals(1, 
usersAndAccessPolicies.getAccessPolicies(ResourceType.Flow.getValue()).size());
+        assertEquals(1, 
usersAndAccessPolicies.getAccessPolicies(ResourceType.Controller.getValue()).size());
+        assertEquals(1, 
usersAndAccessPolicies.getAccessPolicies(ResourceType.System.getValue()).size());
+        assertEquals(1, 
usersAndAccessPolicies.getAccessPolicies(ResourceType.ProcessGroup.getValue() + 
"/" + ROOT_GROUP_ID).size());
+    }
+
+    @Test
+    public void testOnConfiguredWhenLegacyUsersFileProvided() throws Exception 
{
+        
when(configurationContext.getProperty(Mockito.eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE)))
+                .thenReturn(new 
StandardPropertyValue("src/test/resources/authorized-users.xml", null));
+
+        writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
+        authorizer.onConfigured(configurationContext);
+
+        // verify all users got created correctly
+        final Set<User> users = authorizer.getUsers();
+        assertEquals(6, users.size());
+
+        final User user1 = authorizer.getUserByIdentity("user1");
+        assertNotNull(user1);
+
+        final User user2 = authorizer.getUserByIdentity("user2");
+        assertNotNull(user2);
+
+        final User user3 = authorizer.getUserByIdentity("user3");
+        assertNotNull(user3);
+
+        final User user4 = authorizer.getUserByIdentity("user4");
+        assertNotNull(user4);
+
+        final User user5 = authorizer.getUserByIdentity("user5");
+        assertNotNull(user5);
+
+        final User user6 = authorizer.getUserByIdentity("user6");
+        assertNotNull(user6);
+
+        // verify one group got created
+        final Set<Group> groups = authorizer.getGroups();
+        assertEquals(1, groups.size());
+        assertEquals("group1", groups.iterator().next().getName());
+
+        // verify more than one policy got created
+        final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
+        assertTrue(policies.size() > 0);
+
+        // verify user1's policies
+        final Map<String,Set<RequestAction>> user1Policies = 
getResourceActions(policies, user1);
+        assertEquals(4, user1Policies.size());
+
+        assertTrue(user1Policies.containsKey(ResourceType.Flow.getValue()));
+        assertEquals(1, 
user1Policies.get(ResourceType.Flow.getValue()).size());
+        
assertTrue(user1Policies.get(ResourceType.Flow.getValue()).contains(RequestAction.READ));
+
+        
assertTrue(user1Policies.containsKey(ResourceType.ProcessGroup.getValue() + "/" 
+ ROOT_GROUP_ID));
+        assertEquals(1, user1Policies.get(ResourceType.ProcessGroup.getValue() 
+ "/" + ROOT_GROUP_ID).size());
+        assertTrue(user1Policies.get(ResourceType.ProcessGroup.getValue() + 
"/" + ROOT_GROUP_ID).contains(RequestAction.READ));
+
+        // verify user2's policies
+        final Map<String,Set<RequestAction>> user2Policies = 
getResourceActions(policies, user2);
+        assertEquals(1, user2Policies.size());
+
+        
assertTrue(user2Policies.containsKey(ResourceType.Provenance.getValue()));
+        assertEquals(1, 
user2Policies.get(ResourceType.Provenance.getValue()).size());
+        
assertTrue(user2Policies.get(ResourceType.Provenance.getValue()).contains(RequestAction.READ));
+
+        // verify user3's policies
+        final Map<String,Set<RequestAction>> user3Policies = 
getResourceActions(policies, user3);
+        assertEquals(4, user3Policies.size());
+
+        assertTrue(user3Policies.containsKey(ResourceType.Flow.getValue()));
+        assertEquals(1, 
user3Policies.get(ResourceType.Flow.getValue()).size());
+        
assertTrue(user3Policies.get(ResourceType.Flow.getValue()).contains(RequestAction.READ));
+
+        
assertTrue(user3Policies.containsKey(ResourceType.ProcessGroup.getValue() + "/" 
+ ROOT_GROUP_ID));
+        assertEquals(2, user3Policies.get(ResourceType.ProcessGroup.getValue() 
+ "/" + ROOT_GROUP_ID).size());
+
+        // verify user4's policies
+        final Map<String,Set<RequestAction>> user4Policies = 
getResourceActions(policies, user4);
+        assertEquals(6, user4Policies.size());
+
+        assertTrue(user4Policies.containsKey(ResourceType.Flow.getValue()));
+        assertEquals(1, 
user4Policies.get(ResourceType.Flow.getValue()).size());
+        
assertTrue(user4Policies.get(ResourceType.Flow.getValue()).contains(RequestAction.READ));
+
+        
assertTrue(user4Policies.containsKey(ResourceType.ProcessGroup.getValue() + "/" 
+ ROOT_GROUP_ID));
+        assertEquals(1, user4Policies.get(ResourceType.ProcessGroup.getValue() 
+ "/" + ROOT_GROUP_ID).size());
+        assertTrue(user4Policies.get(ResourceType.ProcessGroup.getValue() + 
"/" + ROOT_GROUP_ID).contains(RequestAction.READ));
+
+        assertTrue(user4Policies.containsKey(ResourceType.User.getValue()));
+        assertEquals(2, 
user4Policies.get(ResourceType.User.getValue()).size());
+
+        assertTrue(user4Policies.containsKey(ResourceType.Group.getValue()));
+        assertEquals(2, 
user4Policies.get(ResourceType.Group.getValue()).size());
+
+        assertTrue(user4Policies.containsKey(ResourceType.Policy.getValue()));
+        assertEquals(2, 
user4Policies.get(ResourceType.Policy.getValue()).size());
+
+        // verify user5's policies
+        final Map<String,Set<RequestAction>> user5Policies = 
getResourceActions(policies, user5);
+        assertEquals(1, user5Policies.size());
+
+        assertTrue(user5Policies.containsKey(ResourceType.Proxy.getValue()));
+        assertEquals(2, 
user5Policies.get(ResourceType.Proxy.getValue()).size());
+
+        // verify user6's policies
+        final Map<String,Set<RequestAction>> user6Policies = 
getResourceActions(policies, user6);
+        assertEquals(2, user6Policies.size());
+
+        
assertTrue(user6Policies.containsKey(ResourceType.SiteToSite.getValue()));
+        assertEquals(2, 
user6Policies.get(ResourceType.SiteToSite.getValue()).size());
+    }
+
+    private Map<String,Set<RequestAction>> getResourceActions(final 
Set<AccessPolicy> policies, final User user) {
+        Map<String,Set<RequestAction>> resourceActionMap = new HashMap<>();
+
+        for (AccessPolicy accessPolicy : policies) {
+            if (accessPolicy.getUsers().contains(user.getIdentifier())) {
+                Set<RequestAction> actions = 
resourceActionMap.get(accessPolicy.getResource());
+                if (actions == null) {
+                    actions = new HashSet<>();
+                    resourceActionMap.put(accessPolicy.getResource(), actions);
+                }
+                actions.addAll(accessPolicy.getActions());
+            }
+        }
+
+        return resourceActionMap;
+    }
+
+    @Test(expected = AuthorizerCreationException.class)
+    public void testOnConfiguredWhenBadLegacyUsersFileProvided() throws 
Exception {
+        
when(configurationContext.getProperty(Mockito.eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE)))
+                .thenReturn(new 
StandardPropertyValue("src/test/resources/does-not-exist.xml", null));
+
+        writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
+        authorizer.onConfigured(configurationContext);
+    }
+
+    @Test(expected = AuthorizerCreationException.class)
+    public void testOnConfiguredWhenInitialAdminAndLegacyUsersProvided() 
throws Exception {
+        final String adminIdentity = "admin-user";
+
+        
when(configurationContext.getProperty(Mockito.eq(FileAuthorizer.PROP_INITIAL_ADMIN_IDENTITY)))
+                .thenReturn(new StandardPropertyValue(adminIdentity, null));
+
+        
when(configurationContext.getProperty(Mockito.eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE)))
+                .thenReturn(new 
StandardPropertyValue("src/test/resources/authorized-users.xml", null));
+
+        writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
+        authorizer.onConfigured(configurationContext);
+    }
+
+    @Test
+    public void testOnConfiguredWhenInitialAdminNotProvided() throws Exception 
{
+        writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
+        authorizer.onConfigured(configurationContext);
+
+        final Set<User> users = authorizer.getUsers();
+        assertEquals(0, users.size());
+
+        final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
+        assertEquals(0, policies.size());
+    }
+
+    @Test
     public void testOnConfiguredWhenInitialAdminProvided() throws Exception {
         final String adminIdentity = "admin-user";
 
-        when(configurationContext.getProperty(Mockito.eq("Initial Admin 
Identity")))
+        
when(configurationContext.getProperty(Mockito.eq(FileAuthorizer.PROP_INITIAL_ADMIN_IDENTITY)))
+                .thenReturn(new StandardPropertyValue(adminIdentity, null));
+
+        writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
+        authorizer.onConfigured(configurationContext);
+
+        final Set<User> users = authorizer.getUsers();
+        assertEquals(1, users.size());
+
+        final User adminUser = users.iterator().next();
+        assertEquals(adminIdentity, adminUser.getIdentity());
+
+        final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
+        assertEquals(5, policies.size());
+
+        final String rootGroupResource = ResourceType.ProcessGroup.getValue() 
+ "/" + ROOT_GROUP_ID;
+
+        boolean foundRootGroupPolicy = false;
+        for (AccessPolicy policy : policies) {
+            if (policy.getResource().equals(rootGroupResource)) {
+                foundRootGroupPolicy = true;
+                break;
+            }
+        }
+
+        assertTrue(foundRootGroupPolicy);
+    }
+
+    @Test
+    public void testOnConfiguredWhenInitialAdminProvidedAndNoFlowExists() 
throws Exception {
+        // setup NiFi properties to return a file that does not exist
+        properties = mock(NiFiProperties.class);
+        
when(properties.getRestoreDirectory()).thenReturn(restore.getParentFile());
+        when(properties.getFlowConfigurationFile()).thenReturn(new 
File("src/test/resources/does-not-exist.xml.gz"));
+        authorizer.setNiFiProperties(properties);
+
+        final String adminIdentity = "admin-user";
+        
when(configurationContext.getProperty(Mockito.eq(FileAuthorizer.PROP_INITIAL_ADMIN_IDENTITY)))
                 .thenReturn(new StandardPropertyValue(adminIdentity, null));
 
         writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
@@ -156,20 +376,58 @@ public class FileAuthorizerTest {
 
         final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
         assertEquals(4, policies.size());
+
+        final String rootGroupResource = ResourceType.ProcessGroup.getValue() 
+ "/" + ROOT_GROUP_ID;
+
+        boolean foundRootGroupPolicy = false;
+        for (AccessPolicy policy : policies) {
+            if (policy.getResource().equals(rootGroupResource)) {
+                foundRootGroupPolicy = true;
+                break;
+            }
+        }
+
+        assertFalse(foundRootGroupPolicy);
     }
 
     @Test
-    public void testOnConfiguredWhenInitialAdminNotProvided() throws Exception 
{
+    public void testOnConfiguredWhenInitialAdminProvidedAndFlowIsNull() throws 
Exception {
+        // setup NiFi properties to return a file that does not exist
+        properties = mock(NiFiProperties.class);
+        
when(properties.getRestoreDirectory()).thenReturn(restore.getParentFile());
+        when(properties.getFlowConfigurationFile()).thenReturn(null);
+        authorizer.setNiFiProperties(properties);
+
+        final String adminIdentity = "admin-user";
+        
when(configurationContext.getProperty(Mockito.eq(FileAuthorizer.PROP_INITIAL_ADMIN_IDENTITY)))
+                .thenReturn(new StandardPropertyValue(adminIdentity, null));
+
         writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);
         authorizer.onConfigured(configurationContext);
 
         final Set<User> users = authorizer.getUsers();
-        assertEquals(0, users.size());
+        assertEquals(1, users.size());
+
+        final User adminUser = users.iterator().next();
+        assertEquals(adminIdentity, adminUser.getIdentity());
 
         final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
-        assertEquals(0, policies.size());
+        assertEquals(4, policies.size());
+
+        final String rootGroupResource = ResourceType.ProcessGroup.getValue() 
+ "/" + ROOT_GROUP_ID;
+
+        boolean foundRootGroupPolicy = false;
+        for (AccessPolicy policy : policies) {
+            if (policy.getResource().equals(rootGroupResource)) {
+                foundRootGroupPolicy = true;
+                break;
+            }
+        }
+
+        assertFalse(foundRootGroupPolicy);
     }
 
+
     @Test
     public void testOnConfiguredWhenRestoreDoesNotExist() throws Exception {
         writeAuthorizationsFile(primary, EMPTY_AUTHORIZATIONS_CONCISE);

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/authorized-users-multirole.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/authorized-users-multirole.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/authorized-users-multirole.xml
new file mode 100644
index 0000000..493ed4b
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/authorized-users-multirole.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  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.
+-->
+<users>
+    <user dn="user1" group="group1">
+        <role name="ROLE_MONITOR"/>
+        <role name="ROLE_DFM" />
+    </user>
+</users>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/authorized-users.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/authorized-users.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/authorized-users.xml
new file mode 100644
index 0000000..0515a09
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/authorized-users.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  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.
+-->
+<users>
+    <user dn="user1" group="group1">
+        <role name="ROLE_MONITOR"/>
+    </user>
+    <user dn="user2">
+        <role name="ROLE_PROVENANCE"/>
+    </user>
+    <user dn="user3">
+        <role name="ROLE_DFM"/>
+    </user>
+    <user dn="user4">
+        <role name="ROLE_ADMIN"/>
+    </user>
+    <user dn="user5">
+        <role name="ROLE_PROXY"/>
+    </user>
+    <user dn="user6">
+        <role name="ROLE_NIFI"/>
+    </user>
+</users>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/flow.xml.gz
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/flow.xml.gz
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/flow.xml.gz
new file mode 100644
index 0000000..c2ac4ed
Binary files /dev/null and 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/resources/flow.xml.gz
 differ

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java
index fa205da..3010c92 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java
@@ -29,12 +29,10 @@ import java.util.Map;
 public class StandardAuthorizerConfigurationContext implements 
AuthorizerConfigurationContext {
 
     private final String identifier;
-    private final String rootGroupId;
     private final Map<String, String> properties;
 
-    public StandardAuthorizerConfigurationContext(String identifier, String 
rootGroupId, Map<String, String> properties) {
+    public StandardAuthorizerConfigurationContext(String identifier, 
Map<String, String> properties) {
         this.identifier = identifier;
-        this.rootGroupId = rootGroupId;
         this.properties = Collections.unmodifiableMap(new HashMap<String, 
String>(properties));
     }
 
@@ -44,11 +42,6 @@ public class StandardAuthorizerConfigurationContext 
implements AuthorizerConfigu
     }
 
     @Override
-    public String getRootGroupId() {
-        return rootGroupId;
-    }
-
-    @Override
     public Map<String, String> getProperties() {
         return properties;
     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
index ce8f1bf..1e9b8c2 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
@@ -22,10 +22,58 @@ import java.util.Objects;
 
 public final class ResourceFactory {
 
+    private final static Resource CONNECTION_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.Connection.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Connection";
+        }
+    };
+
+    private final static Resource CONTROLLER_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.Controller.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Controller";
+        }
+    };
+
+    private final static Resource CONTROLLER_SERVICE_RESOURCE = new Resource() 
{
+        @Override
+        public String getIdentifier() {
+            return ResourceType.ControllerService.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Controller Service";
+        }
+    };
+
+    private final static Resource FUNNEL_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.Funnel.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Funnel";
+        }
+    };
+
     private final static Resource FLOW_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
-            return "/flow";
+            return ResourceType.Flow.getValue();
         }
 
         @Override
@@ -34,46 +82,94 @@ public final class ResourceFactory {
         }
     };
 
-    private final static Resource RESOURCE_RESOURCE = new Resource() {
+    private final static Resource GROUP_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
-            return "/resources";
+            return ResourceType.Group.getValue();
         }
 
         @Override
         public String getName() {
-            return "NiFi Resources";
+            return "Group";
         }
     };
 
-    private final static Resource SYSTEM_RESOURCE = new Resource() {
+    private final static Resource INPUT_PORT_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
-            return "/system";
+            return ResourceType.InputPort.getValue();
         }
 
         @Override
         public String getName() {
-            return "System";
+            return "Input Port";
         }
     };
 
-    private final static Resource CONTROLLER_RESOURCE = new Resource() {
+    private final static Resource LABEL_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
-            return "/controller";
+            return ResourceType.Label.getValue();
         }
 
         @Override
         public String getName() {
-            return "Controller";
+            return "Label";
+        }
+    };
+
+    private final static Resource OUTPUT_PORT_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.OutputPort.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Output Port";
+        }
+    };
+
+    private final static Resource POLICY_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.Policy.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Policy";
+        }
+    };
+
+    private final static Resource PROCESSOR_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.Processor.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Processor";
+        }
+    };
+
+    private final static Resource PROCESS_GROUP_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.ProcessGroup.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Process Group";
         }
     };
 
     private final static Resource PROVENANCE_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
-            return "/provenance";
+            return ResourceType.Provenance.getValue();
         }
 
         @Override
@@ -82,22 +178,58 @@ public final class ResourceFactory {
         }
     };
 
-    private final static Resource TOKEN_RESOURCE = new Resource() {
+    private final static Resource PROXY_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
-            return "/token";
+            return ResourceType.Proxy.getValue();
         }
 
         @Override
         public String getName() {
-            return "API access token";
+            return "Proxy User Requests";
+        }
+    };
+
+    private final static Resource REMOTE_PROCESS_GROUP_RESOURCE = new 
Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.RemoteProcessGroup.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Remote Process Group";
+        }
+    };
+
+    private final static Resource REPORTING_TASK_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.ReportingTask.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Reporting Task";
+        }
+    };
+
+    private final static Resource RESOURCE_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.Resource.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "NiFi Resources";
         }
     };
 
     private final static Resource SITE_TO_SITE_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
-            return "/site-to-site";
+            return ResourceType.SiteToSite.getValue();
         }
 
         @Override
@@ -106,19 +238,91 @@ public final class ResourceFactory {
         }
     };
 
-    private final static Resource PROXY_RESOURCE = new Resource() {
+    private final static Resource SYSTEM_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
-            return "/proxy";
+            return ResourceType.System.getValue();
         }
 
         @Override
         public String getName() {
-            return "Proxy User Requests";
+            return "System";
+        }
+    };
+
+    private final static Resource TEMPLATE_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.Template.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Template";
+        }
+    };
+
+    private final static Resource TOKEN_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.Token.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "API access token";
+        }
+    };
+
+    private final static Resource USER_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.User.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "User";
         }
     };
 
     /**
+     * Gets the Resource for accessing Connections.
+     *
+     * @return The resource for accessing connections
+     */
+    public static Resource getConnectionResource() {
+        return CONNECTION_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing the Controller. This includes 
Controller level configuration, bulletins, reporting tasks, and the cluster.
+     *
+     * @return  The resource for accessing the Controller
+     */
+    public static Resource getControllerResource() {
+        return CONTROLLER_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Controller Services.
+     *
+     * @return The resource for accessing Controller Services
+     */
+    public static Resource getControllerServiceResource() {
+        return CONTROLLER_SERVICE_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Funnels.
+     *
+     * @return The resource for accessing Funnels.
+     */
+    public static Resource getFunnelResource() {
+        return FUNNEL_RESOURCE;
+    }
+
+    /**
      * Gets the Resource for accessing the NiFi flow. This includes the data 
flow structure, component status, search results, and banner/about text.
      *
      * @return  The NiFi resource
@@ -128,30 +332,66 @@ public final class ResourceFactory {
     }
 
     /**
-     * Gets the Resource for detailing all available NiFi Resources.
+     * Gets the Resource for accessing Groups which allows management of user 
groups.
      *
-     * @return  The Resource resource
+     * @return The resource for accessing Groups
      */
-    public static Resource getResourceResource() {
-        return RESOURCE_RESOURCE;
+    public static Resource getGroupResource() {
+        return GROUP_RESOURCE;
     }
 
     /**
-     * Gets the Resource for accessing details of the System NiFi is running 
on.
+     * Gets the Resource for accessing Input Ports.
      *
-     * @return  The System resource
+     * @return The resource for accessing Input Ports
      */
-    public static Resource getSystemResource() {
-        return SYSTEM_RESOURCE;
+    public static Resource getInputPortResource() {
+        return INPUT_PORT_RESOURCE;
     }
 
     /**
-     * Gets the Resource for accessing the Controller. This includes 
Controller level configuration, bulletins, reporting tasks, and the cluster.
+     * Gets the Resource for accessing Labels.
      *
-     * @return  The resource for accessing the Controller
+     * @return The resource for accessing Labels
      */
-    public static Resource getControllerResource() {
-        return CONTROLLER_RESOURCE;
+    public static Resource getLabelResource() {
+        return LABEL_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Output Ports.
+     *
+     * @return The resource for accessing Output Ports
+     */
+    public static Resource getOutputPortResource() {
+        return OUTPUT_PORT_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Policies which allows management of 
Access Policies.
+     *
+     * @return The resource for accessing Policies
+     */
+    public static Resource getPolicyResource() {
+        return POLICY_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Processors.
+     *
+     * @return The resource for accessing Processors
+     */
+    public static Resource getProcessorResource() {
+        return PROCESSOR_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Process Groups.
+     *
+     * @return The resource for accessing Process Groups
+     */
+    public static Resource getProcessGroupResource() {
+        return PROCESS_GROUP_RESOURCE;
     }
 
     /**
@@ -165,12 +405,39 @@ public final class ResourceFactory {
     }
 
     /**
-     * Gets the Resource for creating API access tokens.
+     * Gets the Resource for proxying a user request.
      *
-     * @return  The token request resource
+     * @return  The resource for proxying a user request
      */
-    public static Resource getTokenResource() {
-        return TOKEN_RESOURCE;
+    public static Resource getProxyResource() {
+        return PROXY_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Remote Process Groups.
+     *
+     * @return The resource accessing Remote Process Groups
+     */
+    public static Resource getRemoteProcessGroupResource() {
+        return REMOTE_PROCESS_GROUP_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Reporting Tasks.
+     *
+     * @return The resource for accessing Reporting Tasks
+     */
+    public static Resource getReportingTaskResource() {
+        return REPORTING_TASK_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for detailing all available NiFi Resources.
+     *
+     * @return  The Resource resource
+     */
+    public static Resource getResourceResource() {
+        return RESOURCE_RESOURCE;
     }
 
     /**
@@ -184,12 +451,39 @@ public final class ResourceFactory {
     }
 
     /**
-     * Gets the Resource for proxying a user request.
+     * Gets the Resource for accessing details of the System NiFi is running 
on.
      *
-     * @return  The resource for proxying a user request
+     * @return  The System resource
      */
-    public static Resource getProxyResource() {
-        return PROXY_RESOURCE;
+    public static Resource getSystemResource() {
+        return SYSTEM_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Templates.
+     *
+     * @return The Resource for accessing Tempaltes
+     */
+    public static Resource getTemplateResource() {
+        return TEMPLATE_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for creating API access tokens.
+     *
+     * @return  The token request resource
+     */
+    public static Resource getTokenResource() {
+        return TOKEN_RESOURCE;
+    }
+
+    /**
+     * Gets the Resource for accessing Users which includes creating, 
modifying, and deleting Users.
+     *
+     * @return The Resource for accessing Users
+     */
+    public static Resource getUserResource() {
+        return USER_RESOURCE;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
index f3e9b6c..784af6d 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
@@ -17,17 +17,28 @@
 package org.apache.nifi.authorization.resource;
 
 public enum ResourceType {
-    Processor("/processors"),
+    Connection("/connections"),
+    Controller("/controller"),
+    ControllerService("/controller-services"),
+    Funnel("/funnel"),
+    Flow("/flow"),
+    Group("/groups"),
     InputPort("/input-ports"),
+    Label("/labels"),
     OutputPort("/output-ports"),
-    Funnel("/funnel"),
-    Connection("/connections"),
+    Policy("/policies"),
+    Processor("/processors"),
     ProcessGroup("/process-groups"),
+    Provenance("/provenance"),
+    Proxy("/proxy"),
     RemoteProcessGroup("/remote-process-groups"),
-    Label("/labels"),
-    ControllerService("/controller-services"),
     ReportingTask("/reporting-tasks"),
-    Template("/templates");
+    Resource("/resources"),
+    SiteToSite("/site-to-site"),
+    System("/system"),
+    Template("/templates"),
+    Token("/token"),
+    User("/users");
 
     final String value;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/679ad93f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml
index 74255dc..12efb79 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml
@@ -24,5 +24,6 @@
         <class>org.apache.nifi.authorization.FileAuthorizer</class>
         <property name="Authorizations 
File">./conf/authorizations.xml</property>
         <property name="Initial Admin Identity"></property>
+        <property name="Legacy Authorized Users File"></property>
     </authorizer>
 </authorizers>
\ No newline at end of file

Reply via email to