You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ma...@apache.org on 2016/07/26 18:15:54 UTC

[1/2] nifi git commit: NIFI-2346: - Introducing data resource for authorizing provenance events and queue listing. - Authorizing entire proxy chain for data resource and data transfer resource. NIFI-2338: - Ensuring that replay authorization only happens

Repository: nifi
Updated Branches:
  refs/heads/master c27763a12 -> 69586d8bd


http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowFileQueueResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowFileQueueResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowFileQueueResource.java
index cea97da..e5c10ba 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowFileQueueResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowFileQueueResource.java
@@ -24,6 +24,7 @@ import com.wordnik.swagger.annotations.ApiResponses;
 import com.wordnik.swagger.annotations.Authorization;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.ConnectionAuthorizable;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
@@ -120,7 +121,7 @@ public class FlowFileQueueResource extends ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/flowfiles/{flowfile-uuid}")
+    @Path("{id}/flowfiles/{flowfile-uuid}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Gets a FlowFile from a Connection.",
@@ -142,7 +143,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                 value = "The flowfile uuid.",
                 required = true
@@ -170,11 +171,7 @@ public class FlowFileQueueResource extends ApplicationResource {
             }
         }
 
-        // authorize access
-        serviceFacade.authorizeAccess(lookup -> {
-            final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
-            connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
-        });
+        // NOTE - deferred authorization so we can consider flowfile attributes in the access decision
 
         // get the flowfile
         final FlowFileDTO flowfileDto = serviceFacade.getFlowFile(connectionId, flowFileUuid);
@@ -200,7 +197,7 @@ public class FlowFileQueueResource extends ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.WILDCARD)
-    @Path("{connection-id}/flowfiles/{flowfile-uuid}/content")
+    @Path("{id}/flowfiles/{flowfile-uuid}/content")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Gets the content for a FlowFile in a Connection.",
@@ -227,7 +224,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                 value = "The flowfile uuid.",
                 required = true
@@ -255,11 +252,7 @@ public class FlowFileQueueResource extends ApplicationResource {
             }
         }
 
-        // authorize access
-        serviceFacade.authorizeAccess(lookup -> {
-            final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
-            connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
-        });
+        // NOTE - deferred authorization so we can consider flowfile attributes in the access decision
 
         // get the uri of the request
         final String uri = generateResourceUri("flowfile-queues", connectionId, "flowfiles", flowFileUuid, "content");
@@ -300,7 +293,7 @@ public class FlowFileQueueResource extends ApplicationResource {
     @POST
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/listing-requests")
+    @Path("{id}/listing-requests")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Lists the contents of the queue in this connection.",
@@ -325,7 +318,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String id) {
+            @PathParam("id") final String id) {
 
         if (isReplicateRequest()) {
             return replicate(HttpMethod.POST);
@@ -336,8 +329,9 @@ public class FlowFileQueueResource extends ApplicationResource {
         if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
-                final Authorizable connection = lookup.getConnection(id).getAuthorizable();
-                connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                final ConnectionAuthorizable connAuth = lookup.getConnection(id);
+                final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+                dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
             });
         }
         if (validationPhase) {
@@ -371,7 +365,7 @@ public class FlowFileQueueResource extends ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/listing-requests/{listing-request-id}")
+    @Path("{id}/listing-requests/{listing-request-id}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Gets the current status of a listing request for the specified connection.",
@@ -394,7 +388,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                 value = "The listing request id.",
                 required = true
@@ -407,8 +401,9 @@ public class FlowFileQueueResource extends ApplicationResource {
 
         // authorize access
         serviceFacade.authorizeAccess(lookup -> {
-            final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
-            connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+            final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
+            final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
         });
 
         // get the listing request
@@ -433,7 +428,7 @@ public class FlowFileQueueResource extends ApplicationResource {
     @DELETE
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/listing-requests/{listing-request-id}")
+    @Path("{id}/listing-requests/{listing-request-id}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Cancels and/or removes a request to list the contents of this connection.",
@@ -457,7 +452,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                 value = "The listing request id.",
                 required = true
@@ -473,8 +468,9 @@ public class FlowFileQueueResource extends ApplicationResource {
         if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
-                final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
-                connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
+                final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+                dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
             });
         }
         if (validationPhase) {
@@ -507,7 +503,7 @@ public class FlowFileQueueResource extends ApplicationResource {
     @POST
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/drop-requests")
+    @Path("{id}/drop-requests")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Creates a request to drop the contents of the queue in this connection.",
@@ -532,7 +528,7 @@ public class FlowFileQueueResource extends ApplicationResource {
             value = "The connection id.",
             required = true
         )
-        @PathParam("connection-id") final String id) {
+        @PathParam("id") final String id) {
 
         if (isReplicateRequest()) {
             return replicate(HttpMethod.POST);
@@ -543,8 +539,9 @@ public class FlowFileQueueResource extends ApplicationResource {
         if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
-                final Authorizable connection = lookup.getConnection(id).getAuthorizable();
-                connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                final ConnectionAuthorizable connAuth = lookup.getConnection(id);
+                final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+                dataAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
             });
         }
         if (validationPhase) {
@@ -577,7 +574,7 @@ public class FlowFileQueueResource extends ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/drop-requests/{drop-request-id}")
+    @Path("{id}/drop-requests/{drop-request-id}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
             value = "Gets the current status of a drop request for the specified connection.",
@@ -600,7 +597,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                     value = "The connection id.",
                     required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                     value = "The drop request id.",
                     required = true
@@ -613,8 +610,9 @@ public class FlowFileQueueResource extends ApplicationResource {
 
         // authorize access
         serviceFacade.authorizeAccess(lookup -> {
-            final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
-            connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+            final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
+            final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+            dataAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
         });
 
         // get the drop request
@@ -639,7 +637,7 @@ public class FlowFileQueueResource extends ApplicationResource {
     @DELETE
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/drop-requests/{drop-request-id}")
+    @Path("{id}/drop-requests/{drop-request-id}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
             value = "Cancels and/or removes a request to drop the contents of this connection.",
@@ -663,7 +661,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                     value = "The connection id.",
                     required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                     value = "The drop request id.",
                     required = true
@@ -679,8 +677,9 @@ public class FlowFileQueueResource extends ApplicationResource {
         if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
-                final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
-                connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
+                final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+                dataAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
             });
         }
         if (validationPhase) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index 8299181..aa9a8ac 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -30,7 +30,6 @@ import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.resource.ResourceType;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
-import org.apache.nifi.authorization.user.StandardNiFiUser;
 import org.apache.nifi.cluster.coordination.ClusterCoordinator;
 import org.apache.nifi.cluster.protocol.NodeIdentifier;
 import org.apache.nifi.components.PropertyDescriptor;
@@ -69,8 +68,8 @@ import org.apache.nifi.nar.NarCloseable;
 import org.apache.nifi.processor.DataUnit;
 import org.apache.nifi.processor.Processor;
 import org.apache.nifi.processor.Relationship;
-import org.apache.nifi.provenance.ProvenanceRepository;
 import org.apache.nifi.provenance.ProvenanceEventRecord;
+import org.apache.nifi.provenance.ProvenanceRepository;
 import org.apache.nifi.provenance.SearchableFields;
 import org.apache.nifi.provenance.lineage.ComputeLineageSubmission;
 import org.apache.nifi.provenance.search.Query;
@@ -109,7 +108,6 @@ import org.apache.nifi.web.api.dto.search.ComponentSearchResultDTO;
 import org.apache.nifi.web.api.dto.search.SearchResultsDTO;
 import org.apache.nifi.web.api.dto.status.ControllerStatusDTO;
 import org.apache.nifi.web.api.dto.status.StatusHistoryDTO;
-import org.apache.nifi.web.security.ProxiedEntitiesUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -767,7 +765,7 @@ public class ControllerFacade implements Authorizable {
         // add each processor
         for (final ProcessorNode processor : root.findAllProcessors()) {
             resources.add(ResourceFactory.getComponentResource(ResourceType.Processor, processor.getIdentifier(), processor.getName()));
-            resources.add(ResourceFactory.getProvenanceEventResource(processor.getResource()));
+            resources.add(ResourceFactory.getDataResource(processor.getResource()));
         }
 
         // add each label
@@ -778,25 +776,25 @@ public class ControllerFacade implements Authorizable {
         // add each process group
         for (final ProcessGroup processGroup : root.findAllProcessGroups()) {
             resources.add(ResourceFactory.getComponentResource(ResourceType.ProcessGroup, processGroup.getIdentifier(), processGroup.getName()));
-            resources.add(ResourceFactory.getProvenanceEventResource(processGroup.getResource()));
+            resources.add(ResourceFactory.getDataResource(processGroup.getResource()));
         }
 
         // add each remote process group
         for (final RemoteProcessGroup remoteProcessGroup : root.findAllRemoteProcessGroups()) {
             resources.add(ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup, remoteProcessGroup.getIdentifier(), remoteProcessGroup.getName()));
-            resources.add(ResourceFactory.getProvenanceEventResource(remoteProcessGroup.getResource()));
+            resources.add(ResourceFactory.getDataResource(remoteProcessGroup.getResource()));
         }
 
         // add each input port
         for (final Port inputPort : root.findAllInputPorts()) {
             resources.add(ResourceFactory.getComponentResource(ResourceType.InputPort, inputPort.getIdentifier(), inputPort.getName()));
-            resources.add(ResourceFactory.getProvenanceEventResource(inputPort.getResource()));
+            resources.add(ResourceFactory.getDataResource(inputPort.getResource()));
         }
 
         // add each output port
         for (final Port outputPort : root.findAllOutputPorts()) {
             resources.add(ResourceFactory.getComponentResource(ResourceType.OutputPort, outputPort.getIdentifier(), outputPort.getName()));
-            resources.add(ResourceFactory.getProvenanceEventResource(outputPort.getResource()));
+            resources.add(ResourceFactory.getDataResource(outputPort.getResource()));
         }
 
         // add each controller service
@@ -1087,7 +1085,7 @@ public class ControllerFacade implements Authorizable {
             final NiFiUser user = NiFiUserUtils.getNiFiUser();
 
             // get the event in order to get the filename
-            final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId, NiFiUserUtils.getNiFiUser());
+            final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId);
             if (event == null) {
                 throw new ResourceNotFoundException("Unable to find the specified event.");
             }
@@ -1101,7 +1099,8 @@ public class ControllerFacade implements Authorizable {
             }
 
             // authorize the event
-            authorizeEvent(event.getComponentId(), attributes);
+            final Authorizable dataAuthorizable = flowController.createDataAuthorizable(event.getComponentId());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, user, attributes);
 
             // get the filename and fall back to the identifier (should never happen)
             String filename = attributes.get(CoreAttributes.FILENAME.key());
@@ -1137,7 +1136,7 @@ public class ControllerFacade implements Authorizable {
             }
 
             // lookup the original event
-            final ProvenanceEventRecord originalEvent = flowController.getProvenanceRepository().getEvent(eventId, NiFiUserUtils.getNiFiUser());
+            final ProvenanceEventRecord originalEvent = flowController.getProvenanceRepository().getEvent(eventId);
             if (originalEvent == null) {
                 throw new ResourceNotFoundException("Unable to find the specified event.");
             }
@@ -1156,67 +1155,6 @@ public class ControllerFacade implements Authorizable {
     }
 
     /**
-     * Authorizes access to a provenance event generated by the specified component and containing the specified eventAttributes.
-     *
-     * @param componentId component id
-     * @param eventAttributes event attributes
-     */
-    private AuthorizationResult checkAuthorizationForEvent(final String componentId, final Map<String, String> eventAttributes) {
-        AuthorizationResult result = null;
-
-        // calculate the dn chain
-        final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final List<String> dnChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
-        for (final String identity : dnChain) {
-            final Authorizable eventAuthorizable = flowController.createProvenanceAuthorizable(componentId);
-            final String clientAddress = user.getIdentity().equals(identity) ? user.getClientAddress() : null;
-            final NiFiUser chainUser = new StandardNiFiUser(identity, clientAddress) {
-                @Override
-                public boolean isAnonymous() {
-                    // allow current user to drive anonymous flag as anonymous users are never chained... supports single user case
-                    return user.isAnonymous();
-                }
-            };
-
-            result = eventAuthorizable.checkAuthorization(authorizer, RequestAction.READ, chainUser, eventAttributes);
-            if (!Result.Approved.equals(result.getResult())) {
-                break;
-            }
-        }
-
-        if (result == null) {
-            result = AuthorizationResult.denied();
-        }
-
-        return result;
-    }
-
-    /**
-     * Authorizes access to a provenance event generated by the specified component and containing the specified eventAttributes.
-     *
-     * @param componentId component id
-     * @param eventAttributes event attributes
-     */
-    private void authorizeEvent(final String componentId, final Map<String, String> eventAttributes) {
-        // calculate the dn chain
-        final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final List<String> dnChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
-        for (final String identity : dnChain) {
-            final Authorizable eventAuthorizable = flowController.createProvenanceAuthorizable(componentId);
-            final String clientAddress = user.getIdentity().equals(identity) ? user.getClientAddress() : null;
-            final NiFiUser chainUser = new StandardNiFiUser(identity, clientAddress) {
-                @Override
-                public boolean isAnonymous() {
-                    // allow current user to drive anonymous flag as anonymous users are never chained... supports single user case
-                    return user.isAnonymous();
-                }
-            };
-
-            eventAuthorizable.authorize(authorizer, RequestAction.READ, chainUser, eventAttributes);
-        }
-    }
-
-    /**
      * Authorizes access to replay a specified provenance event.
      *
      * @param componentId component id
@@ -1229,16 +1167,17 @@ public class ControllerFacade implements Authorizable {
             return AuthorizationResult.denied();
         }
 
-        final AuthorizationResult result = checkAuthorizationForEvent(componentId, eventAttributes);
+        final NiFiUser user = NiFiUserUtils.getNiFiUser();
+        final Authorizable dataAuthorizable = flowController.createDataAuthorizable(componentId);
+
+        // ensure we can read the data
+        final AuthorizationResult result = dataAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, eventAttributes);
         if (!Result.Approved.equals(result.getResult())) {
             return result;
         }
 
-        // authorize write permissions for the queue
-        final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId());
-        final Connection connection = rootGroup.findConnection(connectionId);
-        return connection.checkAuthorization(authorizer, RequestAction.WRITE, user);
+        // ensure we can write the data
+        return dataAuthorizable.checkAuthorization(authorizer, RequestAction.WRITE, user, eventAttributes);
     }
 
     /**
@@ -1254,13 +1193,12 @@ public class ControllerFacade implements Authorizable {
             throw new AccessDeniedException("The connection id is unknown.");
         }
 
-        authorizeEvent(componentId, eventAttributes);
-
-        // authorize write permissions for the queue
         final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId());
-        final Connection connection = rootGroup.findConnection(connectionId);
-        connection.authorize(authorizer, RequestAction.WRITE, user);
+        final Authorizable dataAuthorizable = flowController.createDataAuthorizable(componentId);
+
+        // ensure we can read and write the data
+        dataAuthorizable.authorize(authorizer, RequestAction.READ, user, eventAttributes);
+        dataAuthorizable.authorize(authorizer, RequestAction.WRITE, user, eventAttributes);
     }
 
     /**
@@ -1271,14 +1209,15 @@ public class ControllerFacade implements Authorizable {
      */
     public ProvenanceEventDTO getProvenanceEvent(final Long eventId) {
         try {
-            final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId, NiFiUserUtils.getNiFiUser());
+            final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId);
             if (event == null) {
                 throw new ResourceNotFoundException("Unable to find the specified event.");
             }
 
             // get the flowfile attributes and authorize the event
             final Map<String, String> attributes = event.getAttributes();
-            authorizeEvent(event.getComponentId(), attributes);
+            final Authorizable dataAuthorizable = flowController.createDataAuthorizable(event.getComponentId());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser(), attributes);
 
             // convert the event
             return createProvenanceEventDto(event);
@@ -1293,8 +1232,8 @@ public class ControllerFacade implements Authorizable {
      * @param componentId component id
      * @return authorizable
      */
-    public Authorizable getProvenanceEventAuthorizable(final String componentId) {
-        return flowController.createProvenanceAuthorizable(componentId);
+    public Authorizable getDataAuthorizable(final String componentId) {
+        return flowController.createDataAuthorizable(componentId);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
index d3f8965..05b7fd7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
@@ -46,7 +46,18 @@ public interface AccessPolicyDAO {
     AccessPolicy getAccessPolicy(String accessPolicyId);
 
     /**
-     * Gets the access policy according to the action and authorizable.
+     * Gets the access policy according to the action and authorizable. Will return null
+     * if no policy exists for the specific resource.
+     *
+     * @param requestAction action
+     * @param resource resource
+     * @return access policy
+     */
+    AccessPolicy getAccessPolicy(RequestAction requestAction, String resource);
+
+    /**
+     * Gets the access policy according to the action and authorizable. Will return the
+     * effective policy if no policy exists for the specific authorizable.
      *
      * @param requestAction action
      * @param authorizable authorizable

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
index a337854..16cf03f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
@@ -16,16 +16,11 @@
  */
 package org.apache.nifi.web.dao.impl;
 
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.authorization.AccessDeniedException;
-import org.apache.nifi.authorization.AuthorizationResult;
-import org.apache.nifi.authorization.AuthorizationResult.Result;
 import org.apache.nifi.authorization.Authorizer;
 import org.apache.nifi.authorization.RequestAction;
-import org.apache.nifi.authorization.UserContextKeys;
+import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
-import org.apache.nifi.authorization.user.StandardNiFiUser;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.ConnectableType;
 import org.apache.nifi.connectable.Connection;
@@ -50,7 +45,6 @@ import org.apache.nifi.web.api.dto.ConnectableDTO;
 import org.apache.nifi.web.api.dto.ConnectionDTO;
 import org.apache.nifi.web.api.dto.PositionDTO;
 import org.apache.nifi.web.dao.ConnectionDAO;
-import org.apache.nifi.web.security.ProxiedEntitiesUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -60,7 +54,6 @@ import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -139,6 +132,11 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO
                 throw new ResourceNotFoundException(String.format("The FlowFile with UUID %s is no longer in the active queue.", flowFileUuid));
             }
 
+            // get the attributes and ensure appropriate access
+            final Map<String, String> attributes = flowFile.getAttributes();
+            final Authorizable dataAuthorizable = flowController.createDataAuthorizable(connection.getSource().getIdentifier());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser(), attributes);
+
             return flowFile;
         } catch (final IOException ioe) {
             logger.error(String.format("Unable to get the flowfile (%s) at this time.", flowFileUuid), ioe);
@@ -597,26 +595,10 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO
                 throw new ResourceNotFoundException(String.format("The FlowFile with UUID %s is no longer in the active queue.", flowFileUuid));
             }
 
+            // get the attributes and ensure appropriate access
             final Map<String, String> attributes = flowFile.getAttributes();
-
-            // calculate the dn chain
-            final List<String> dnChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
-            dnChain.forEach(identity -> {
-                // build the request
-                final Map<String,String> userContext;
-                if (!StringUtils.isBlank(user.getClientAddress())) {
-                    userContext = new HashMap<>();
-                    userContext.put(UserContextKeys.CLIENT_ADDRESS.name(), user.getClientAddress());
-                } else {
-                    userContext = null;
-                }
-
-                final NiFiUser chainUser = new StandardNiFiUser(identity, user.getClientAddress());
-                final AuthorizationResult result = connection.checkAuthorization(authorizer, RequestAction.WRITE, chainUser, attributes);
-                if (!Result.Approved.equals(result.getResult())) {
-                    throw new AccessDeniedException(result.getExplanation());
-                }
-            });
+            final Authorizable dataAuthorizable = flowController.createDataAuthorizable(connection.getSource().getIdentifier());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, user, attributes);
 
             // get the filename and fall back to the identifier (should never happen)
             String filename = attributes.get(CoreAttributes.FILENAME.key());

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
index 7488fe1..41051e1 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
@@ -180,6 +180,11 @@ public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, UserGr
     }
 
     @Override
+    public AccessPolicy getAccessPolicy(final RequestAction requestAction, final String resource) {
+        return findAccessPolicy(requestAction, resource);
+    }
+
+    @Override
     public AccessPolicy getAccessPolicy(final RequestAction requestAction, final Authorizable authorizable) {
         final String resource = authorizable.getResource().getIdentifier();
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
index 605e98b..0ff9fed 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
@@ -16,17 +16,19 @@
  */
 package org.apache.nifi.web.security;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 /**
  *
  */
@@ -72,34 +74,11 @@ public class ProxiedEntitiesUtils {
      */
     public static String buildProxiedEntitiesChainString(final NiFiUser user) {
         // calculate the dn chain
-        final List<String> proxyChain = buildProxiedEntitiesChain(user);
+        final List<String> proxyChain = NiFiUserUtils.buildProxiedEntitiesChain(user);
         return formatProxyDn(StringUtils.join(proxyChain, "><"));
     }
 
     /**
-     * Builds the proxy chain for the specified user.
-     *
-     * @param user The current user
-     * @return The proxy chain for that user in List form
-     */
-    public static List<String> buildProxiedEntitiesChain(final NiFiUser user) {
-        // calculate the dn chain
-        final List<String> proxyChain = new ArrayList<>();
-
-        // build the dn chain
-        NiFiUser chainedUser = user;
-        do {
-            // add the entry for this user
-            proxyChain.add(chainedUser.getIdentity());
-
-            // go to the next user in the chain
-            chainedUser = chainedUser.getChain();
-        } while (chainedUser != null);
-
-        return proxyChain;
-    }
-
-    /**
      * Builds the proxy chain from the specified request and user.
      *
      * @param request the request

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css
index 1c16d13..fbc0de5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css
@@ -68,7 +68,7 @@
 */
 
 body.login-body input, body.login-body textarea {
-    width: 400px;
+    width: 412px;
 }
 
 div.login-container {

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
index 4057334..aee9aaf 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
@@ -999,8 +999,9 @@ nf.Actions = (function () {
                         $('#drop-request-status-message').text(dropRequest.state);
 
                         // update the current number of enqueued flowfiles
-                        if (nf.Common.isDefinedAndNotNull(connection.status) && nf.Common.isDefinedAndNotNull(dropRequest.currentCount)) {
+                        if (nf.Common.isDefinedAndNotNull(dropRequest.currentCount)) {
                             connection.status.queued = dropRequest.current;
+                            connection.status.aggregateSnapshot.queued = dropRequest.current;
                             nf.Connection.refresh(connection.id);
                         }
 
@@ -1028,13 +1029,19 @@ nf.Actions = (function () {
                         }).done(function (response) {
                             dropRequest = response.dropRequest;
                             processDropRequest(nextDelay);
-                        }).fail(completeDropRequest);
+                        }).fail(function (xhr, status, error) {
+                            if (xhr.status === 403) {
+                                nf.Common.handleAjaxError(xhr, status, error);
+                            } else {
+                                completeDropRequest()
+                            }
+                        });
                     };
 
                     // issue the request to delete the flow files
                     $.ajax({
                         type: 'POST',
-                        url: '../nifi-api/flowfile-queues/' + connection.id + '/drop-requests',
+                        url: '../nifi-api/flowfile-queues/' + encodeURIComponent(connection.id) + '/drop-requests',
                         dataType: 'json',
                         contentType: 'application/json'
                     }).done(function (response) {
@@ -1047,7 +1054,13 @@ nf.Actions = (function () {
                         // process the drop request
                         dropRequest = response.dropRequest;
                         processDropRequest(1);
-                    }).fail(completeDropRequest);
+                    }).fail(function (xhr, status, error) {
+                        if (xhr.status === 403) {
+                            nf.Common.handleAjaxError(xhr, status, error);
+                        } else {
+                            completeDropRequest()
+                        }
+                    });
                 }
             });
         },

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
index 2282fe2..326f1a1 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
@@ -316,10 +316,6 @@ nf.ContextMenu = (function () {
      * @param {selection} selection
      */
     var canEmptyQueue = function (selection) {
-        if (nf.CanvasUtils.canModify(selection) === false) {
-            return false;
-        }
-        
         return isConnection(selection);
     };
 
@@ -329,10 +325,6 @@ nf.ContextMenu = (function () {
      * @param {selection} selection
      */
     var canListQueue = function (selection) {
-        if (nf.CanvasUtils.canModify(selection) === false) {
-            return false;
-        }
-        
         return isConnection(selection);
     };
     

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
index 4ba2bcd..c207e80 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
@@ -308,17 +308,13 @@ nf.PolicyManagement = (function () {
                 value: 'write-component',
                 description: 'Allows users to modify component configuration details'
             }, {
-                text: 'view the provenance events',
-                value: 'read-provenance-events',
-                description: 'Allows users to access provenance events and content for this component'
+                text: 'view the data',
+                value: 'read-data',
+                description: 'Allows users to view metadata and content for this component through provenance data and flowfile queues in outbound connections'
             }, {
-                text: 'view the policies',
-                value: 'read-policies',
-                description: 'Allows users to view the list of users who can view/modify this component'
-            }, {
-                text: 'modify the policies',
-                value: 'write-policies',
-                description: 'Allows users to modify the list of users who can view/modify this component'
+                text: 'modify the data',
+                value: 'write-data',
+                description: 'Allows users to empty flowfile queues in outbound connections and submit replays'
             }, {
                 text: 'receive data via site-to-site',
                 value: 'write-receive-data',
@@ -329,6 +325,14 @@ nf.PolicyManagement = (function () {
                 value: 'write-send-data',
                 description: 'Allows this port to send data to these NiFi instances',
                 disabled: true
+            }, {
+                text: 'view the policies',
+                value: 'read-policies',
+                description: 'Allows users to view the list of users who can view/modify this component'
+            }, {
+                text: 'modify the policies',
+                value: 'write-policies',
+                description: 'Allows users to modify the list of users who can view/modify this component'
             }],
             select: function (option) {
                 if (initialized) {
@@ -338,9 +342,12 @@ nf.PolicyManagement = (function () {
                         $('#selected-policy-action').text('read');
                     } else if (option.value === 'write-component') {
                         $('#selected-policy-action').text('write');
-                    } else if (option.value === 'read-provenance-events') {
+                    } else if (option.value === 'read-data') {
                         $('#selected-policy-action').text('read');
-                        resource = ('provenance-events/' + resource);
+                        resource = ('data/' + resource);
+                    } else if (option.value === 'write-data') {
+                        $('#selected-policy-action').text('write');
+                        resource = ('data/' + resource);
                     } else if (option.value === 'read-policies') {
                         $('#selected-policy-action').text('read');
                         resource = ('policies/' + resource);
@@ -380,7 +387,11 @@ nf.PolicyManagement = (function () {
         var actionFormatter = function (row, cell, value, columnDef, dataContext) {
             var markup = '';
 
-            markup += '<div title="Remove" class="pointer delete-user fa fa-trash"></div>';
+            // see if the user has permissions for the current policy
+            var currentEntity = $('#policy-table').data('policy');
+            if (currentEntity.permissions.canWrite === true) {
+                markup += '<div title="Remove" class="pointer delete-user fa fa-trash"></div>';
+            }
 
             return markup;
         };
@@ -538,7 +549,11 @@ nf.PolicyManagement = (function () {
                 dataType: 'json'
             }).done(function () {
                 loadPolicy();
-            }).fail(nf.Common.handleAjaxError);
+            }).fail(function (xhr, status, error) {
+                nf.Common.handleAjaxError(xhr, status, error);
+                resetPolicy();
+                loadPolicy();
+            });
         } else {
             nf.Dialog.showOkDialog({
                 headerText: 'Update Policy',
@@ -600,6 +615,7 @@ nf.PolicyManagement = (function () {
 
         // re-sort and clear selection after updating
         policyData.reSort();
+        policyGrid.invalidate();
         policyGrid.getSelectionModel().setSelectedRows([]);
     };
 
@@ -634,20 +650,21 @@ nf.PolicyManagement = (function () {
 
         // store the current policy version
         $('#policy-table').data('policy', policyEntity);
-        
-        // allow removal and modification as the policy is not inherited
-        $('#new-policy-user-button').prop('disabled', false);
+
+        // allow modification if allowed
+        $('#new-policy-user-button').prop('disabled', policyEntity.permissions.canWrite === false);
 
         // see if the policy is for this resource
         if (resourceAndAction.resource === policy.resource) {
             // allow remove when policy is not inherited
-            $('#delete-policy-button').prop('disabled', false);
+            $('#delete-policy-button').prop('disabled', policyEntity.permissions.canWrite === false);
         } else {
             $('#policy-message').text('Showing effective policy inherited from ' + convertToHumanReadableResource(policy.resource) + '. ');
-            $('#new-policy-message').hide();
+
+            // policy is inherited, we do not know if the user has permissions to modify the desired policy... show button and let server decide
             $('#override-policy-message').show();
 
-            // require non inherited policy for removal
+            // to not support policy deletion
             $('#delete-policy-button').prop('disabled', true);
         }
 
@@ -660,7 +677,6 @@ nf.PolicyManagement = (function () {
      */
     var loadPolicy = function () {
         var resourceAndAction = getSelectedResourceAndAction();
-
         return $.Deferred(function (deferred) {
             $.ajax({
                 type: 'GET',
@@ -673,7 +689,7 @@ nf.PolicyManagement = (function () {
                 $('#policy-last-refreshed').text(policyEntity.generated);
 
                 // ensure appropriate actions for the loaded policy
-                if (policyEntity.permissions.canRead === true && policyEntity.permissions.canWrite === true) {
+                if (policyEntity.permissions.canRead === true) {
                     var policy = policyEntity.component;
 
                     $('#policy-message').text(policy.resource);
@@ -684,9 +700,10 @@ nf.PolicyManagement = (function () {
                     // reset the policy
                     resetPolicy();
 
-                    // show an appropriate message
-                    $('#policy-message').text('No policy for the specified resource and not authorized to access the inherited policy. ');
-                    $('#new-policy-message').hide();
+                    // since we cannot read, the policy may be inherited or not... we cannot tell
+                    $('#policy-message').text('Not authorized to view the policy.');
+
+                    // allow option to override because we don't know if it's supported or not
                     $('#override-policy-message').show();
                 }
 
@@ -698,8 +715,9 @@ nf.PolicyManagement = (function () {
 
                     // show an appropriate message
                     $('#policy-message').text('No policy for the specified resource.');
+
+                    // we don't know if the user has permissions to the desired policy... show create button and allow the server to decide
                     $('#new-policy-message').show();
-                    $('#override-policy-message').hide();
 
                     deferred.resolve();
                 } else if (xhr.status === 403) {
@@ -708,8 +726,6 @@ nf.PolicyManagement = (function () {
 
                     // show an appropriate message
                     $('#policy-message').text('Not authorized to access the policy for the specified resource.');
-                    $('#new-policy-message').hide();
-                    $('#override-policy-message').hide();
 
                     deferred.resolve();
                 } else {
@@ -747,7 +763,19 @@ nf.PolicyManagement = (function () {
             dataType: 'json',
             contentType: 'application/json'
         }).done(function (policyEntity) {
-            populatePolicy(policyEntity);
+            // ensure appropriate actions for the loaded policy
+            if (policyEntity.permissions.canRead === true) {
+                var policy = policyEntity.component;
+
+                $('#policy-message').text(policy.resource);
+
+                // populate the policy details
+                populatePolicy(policyEntity);
+            } else {
+                // the request succeeded but we don't have access to the policy... reset/reload the policy
+                resetPolicy();
+                loadPolicy();
+            }
         }).fail(nf.Common.handleAjaxError);
     };
 
@@ -792,7 +820,7 @@ nf.PolicyManagement = (function () {
                 contentType: 'application/json'
             }).done(function (policyEntity) {
                 // ensure appropriate actions for the loaded policy
-                if (policyEntity.permissions.canRead === true && policyEntity.permissions.canWrite === true) {
+                if (policyEntity.permissions.canRead === true) {
                     var policy = policyEntity.component;
 
                     $('#policy-message').text(policy.resource);
@@ -800,15 +828,15 @@ nf.PolicyManagement = (function () {
                     // populate the policy details
                     populatePolicy(policyEntity);
                 } else {
-                    // reset the policy
+                    // the request succeeded but we don't have access to the policy... reset/reload the policy
                     resetPolicy();
-
-                    // show an appropriate message
-                    $('#policy-message').text('No policy for the specified resource and not authorized to access the inherited policy. ');
-                    $('#new-policy-message').hide();
-                    $('#override-policy-message').show();
+                    loadPolicy();
                 }
-            }).fail(nf.Common.handleAjaxError);
+            }).fail(function (xhr, status, error) {
+                nf.Common.handleAjaxError(xhr, status, error)
+                resetPolicy();
+                loadPolicy();
+            });
         } else {
             nf.Dialog.showOkDialog({
                 headerText: 'Update Policy',
@@ -872,35 +900,6 @@ nf.PolicyManagement = (function () {
         $('div.policy-selected-component-container').hide();
     };
 
-    /**
-     * Populates the initial policy resource.
-     *
-     * @param resource
-     */
-    var populateComponentResource = function (resource) {
-        // record the initial resource type
-        $('#selected-policy-component-type').text(resource);
-
-        var policyTarget = $('#component-policy-target').combo('getSelectedOption').value;
-        if (policyTarget === 'read-component') {
-            $('#selected-policy-action').text('read');
-        } else if (policyTarget === 'write-component') {
-            $('#selected-policy-action').text('write');
-        } else if (policyTarget === 'read-provenance-events') {
-            $('#selected-policy-action').text('read');
-            resource = ('provenance-events/' + resource);
-        } else if (policyTarget === 'read-policies') {
-            $('#selected-policy-action').text('read');
-            resource = ('policies/' + resource);
-        } else if (policyTarget === 'write-policies') {
-            $('#selected-policy-action').text('write');
-            resource = ('policies/' + resource);
-        }
-
-        // update the policy type
-        $('#selected-policy-type').text(resource);
-    };
-    
     return {
         /**
          * Initializes the settings page.
@@ -909,6 +908,13 @@ nf.PolicyManagement = (function () {
             initAddTenantToPolicyDialog();
             initPolicyTable();
 
+            $('#policy-refresh-button').on('click', function () {
+                loadPolicy();
+            });
+
+            // reset the policy to initialize
+            resetPolicy();
+
             // mark as initialized
             initialized = true;
         },
@@ -940,7 +946,7 @@ nf.PolicyManagement = (function () {
             $('#global-policy-controls').hide();
 
             // update the visibility
-            if (d.permissions.canRead) {
+            if (d.permissions.canRead === true) {
                 $('#policy-selected-controller-service-container div.policy-selected-component-name').text(d.component.name);
             } else {
                 $('#policy-selected-controller-service-container div.policy-selected-component-name').text(d.id);
@@ -949,7 +955,17 @@ nf.PolicyManagement = (function () {
 
             // populate the initial resource
             $('#selected-policy-component-id').text(d.id);
-            populateComponentResource('controller-services');
+            $('#selected-policy-component-type').text('controller-services');
+            $('#component-policy-target')
+                .combo('setOptionEnabled', {
+                    value: 'write-receive-data'
+                }, false)
+                .combo('setOptionEnabled', {
+                    value: 'write-send-data'
+                }, false)
+                .combo('setSelectedOption', {
+                    value: 'read-component'
+                });
 
             return loadPolicy().always(showPolicy);
         },
@@ -968,7 +984,7 @@ nf.PolicyManagement = (function () {
             $('#global-policy-controls').hide();
 
             // update the visibility
-            if (d.permissions.canRead) {
+            if (d.permissions.canRead === true) {
                 $('#policy-selected-reporting-task-container div.policy-selected-component-name').text(d.component.name);
             } else {
                 $('#policy-selected-reporting-task-container div.policy-selected-component-name').text(d.id);
@@ -977,7 +993,17 @@ nf.PolicyManagement = (function () {
             
             // populate the initial resource
             $('#selected-policy-component-id').text(d.id);
-            populateComponentResource('reporting-tasks');
+            $('#selected-policy-component-type').text('reporting-tasks');
+            $('#component-policy-target')
+                .combo('setOptionEnabled', {
+                    value: 'write-receive-data'
+                }, false)
+                .combo('setOptionEnabled', {
+                    value: 'write-send-data'
+                }, false)
+                .combo('setSelectedOption', {
+                    value: 'read-component'
+                });
 
             return loadPolicy().always(showPolicy);
         },
@@ -996,7 +1022,7 @@ nf.PolicyManagement = (function () {
             $('#global-policy-controls').hide();
 
             // update the visibility
-            if (d.permissions.canRead) {
+            if (d.permissions.canRead === true) {
                 $('#policy-selected-template-container div.policy-selected-component-name').text(d.template.name);
             } else {
                 $('#policy-selected-template-container div.policy-selected-component-name').text(d.id);
@@ -1005,7 +1031,17 @@ nf.PolicyManagement = (function () {
 
             // populate the initial resource
             $('#selected-policy-component-id').text(d.id);
-            populateComponentResource('templates');
+            $('#selected-policy-component-type').text('templates');
+            $('#component-policy-target')
+                .combo('setOptionEnabled', {
+                    value: 'write-receive-data'
+                }, false)
+                .combo('setOptionEnabled', {
+                    value: 'write-send-data'
+                }, false)
+                .combo('setSelectedOption', {
+                    value: 'read-component'
+                });
 
             return loadPolicy().always(showPolicy);
         },
@@ -1028,6 +1064,15 @@ nf.PolicyManagement = (function () {
             if (selection.empty()) {
                 $('#selected-policy-component-id').text(nf.Canvas.getGroupId());
                 resource = 'process-groups';
+
+                // disable site to site option
+                $('#component-policy-target')
+                    .combo('setOptionEnabled', {
+                        value: 'write-receive-data'
+                    }, false)
+                    .combo('setOptionEnabled', {
+                        value: 'write-send-data'
+                    }, false);
             } else {
                 var d = selection.datum();
                 $('#selected-policy-component-id').text(d.id);
@@ -1059,7 +1104,10 @@ nf.PolicyManagement = (function () {
             }
 
             // populate the initial resource
-            populateComponentResource(resource);
+            $('#selected-policy-component-type').text(resource);
+            $('#component-policy-target').combo('setSelectedOption', {
+                value: 'read-component'
+            });
 
             return loadPolicy().always(showPolicy);
         },

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java
index e01c2b1..7e8b9a6 100644
--- a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java
+++ b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java
@@ -411,7 +411,7 @@ public class PersistentProvenanceRepository implements ProvenanceRepository {
 
         final Authorizable eventAuthorizable;
         try {
-            eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
+            eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
         } catch (final ResourceNotFoundException rnfe) {
             return false;
         }
@@ -425,7 +425,7 @@ public class PersistentProvenanceRepository implements ProvenanceRepository {
             return;
         }
 
-        final Authorizable eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
+        final Authorizable eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
         eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java
index b65d99d..10026cf 100644
--- a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java
+++ b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java
@@ -243,7 +243,7 @@ public class VolatileProvenanceRepository implements ProvenanceRepository {
 
         final Authorizable eventAuthorizable;
         try {
-            eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
+            eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
         } catch (final ResourceNotFoundException rnfe) {
             return false;
         }
@@ -257,7 +257,7 @@ public class VolatileProvenanceRepository implements ProvenanceRepository {
             return;
         }
 
-        final Authorizable eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
+        final Authorizable eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
         eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
     }
 


[2/2] nifi git commit: NIFI-2346: - Introducing data resource for authorizing provenance events and queue listing. - Authorizing entire proxy chain for data resource and data transfer resource. NIFI-2338: - Ensuring that replay authorization only happens

Posted by ma...@apache.org.
NIFI-2346:
- Introducing data resource for authorizing provenance events and queue listing.
- Authorizing entire proxy chain for data resource and data transfer resource.
NIFI-2338:
- Ensuring that replay authorization only happens once.

- Allowing users with access to policies for a component to be able to access all policies for that component.
-- Includes the component, data, data transfers, and policies.
- Fixing drop request completion to update the correct queued field.
- Fixing access control check for listing and emptying queues.
- Reseting selected policy when re-opening the policy management page.
- Fixing button/link visibility for available actions in policy management page.
- Fixing policy issues with policy removal when the underlying component is deleted.
- Updating file authorizer seeding to grant data access to node's in the cluster.

This closes #720.


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

Branch: refs/heads/master
Commit: 69586d8bd00b0e1e6cc606411363851b75684554
Parents: c27763a
Author: Matt Gilman <ma...@gmail.com>
Authored: Tue Jul 26 11:21:22 2016 -0400
Committer: Mark Payne <ma...@hotmail.com>
Committed: Tue Jul 26 14:15:36 2016 -0400

----------------------------------------------------------------------
 .../authorization/resource/Authorizable.java    |   8 +
 .../ProvenanceAuthorizableFactory.java          |   7 +-
 .../nifi/authorization/FileAuthorizer.java      |   9 +
 .../nifi/authorization/RoleAccessPolicy.java    |   8 +-
 .../nifi/authorization/FileAuthorizerTest.java  |   6 +-
 .../resource/AccessPolicyAuthorizable.java      |  98 ++++++++--
 .../resource/DataAuthorizable.java              | 125 ++++++++++++
 .../resource/DataTransferAuthorizable.java      |   5 +-
 ...rcePolicyPermissionsThroughBaseResource.java |  38 ++++
 .../resource/ProvenanceEventAuthorizable.java   |  41 ----
 .../authorization/resource/ResourceFactory.java |  12 +-
 .../authorization/resource/ResourceType.java    |   2 +-
 .../nifi/authorization/user/NiFiUserUtils.java  |  26 +++
 .../org/apache/nifi/controller/Template.java    |  19 +-
 .../nifi/connectable/StandardConnection.java    |   8 +
 .../apache/nifi/controller/FlowController.java  |  73 ++++---
 .../nifi/authorization/AuthorizableLookup.java  |   7 +
 .../StandardAuthorizableLookup.java             |  17 +-
 .../nifi/web/StandardNiFiContentAccess.java     |  12 +-
 .../nifi/web/StandardNiFiServiceFacade.java     | 106 +++++-----
 .../nifi/web/api/AccessPolicyResource.java      |  10 +-
 .../nifi/web/api/FlowFileQueueResource.java     |  75 ++++---
 .../nifi/web/controller/ControllerFacade.java   | 115 +++--------
 .../apache/nifi/web/dao/AccessPolicyDAO.java    |  13 +-
 .../web/dao/impl/StandardConnectionDAO.java     |  36 +---
 .../impl/StandardPolicyBasedAuthorizerDAO.java  |   5 +
 .../nifi/web/security/ProxiedEntitiesUtils.java |  39 +---
 .../nifi-web-ui/src/main/webapp/css/login.css   |   2 +-
 .../src/main/webapp/js/nf/canvas/nf-actions.js  |  21 +-
 .../main/webapp/js/nf/canvas/nf-context-menu.js |   8 -
 .../webapp/js/nf/canvas/nf-policy-management.js | 194 ++++++++++++-------
 .../PersistentProvenanceRepository.java         |   4 +-
 .../VolatileProvenanceRepository.java           |   4 +-
 33 files changed, 688 insertions(+), 465 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
----------------------------------------------------------------------
diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
index 09829a9..cc0d8fc 100644
--- a/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
+++ b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
@@ -69,6 +69,10 @@ public interface Authorizable {
      * @return is authorized
      */
     default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
+        if (user == null) {
+            return AuthorizationResult.denied("Unknown user");
+        }
+
         final Map<String,String> userContext;
         if (user.getClientAddress() != null && !user.getClientAddress().trim().isEmpty()) {
             userContext = new HashMap<>();
@@ -128,6 +132,10 @@ public interface Authorizable {
      * @param resourceContext resource context
      */
     default void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
+        if (user == null) {
+            throw new AccessDeniedException("Unknown user");
+        }
+
         final Map<String,String> userContext;
         if (user.getClientAddress() != null && !user.getClientAddress().trim().isEmpty()) {
             userContext = new HashMap<>();

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java
----------------------------------------------------------------------
diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java b/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java
index 23d6b3d..9699041 100644
--- a/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java
+++ b/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java
@@ -23,13 +23,14 @@ import org.apache.nifi.web.ResourceNotFoundException;
 public interface ProvenanceAuthorizableFactory {
 
     /**
-     * Generates an Authorizable object for the Provenance events of the component with the given ID
+     * Generates an Authorizable object for the Data of the component with the given ID. This includes
+     * provenance data and queue's on outgoing relationships.
      *
-     * @param componentId the ID of the component to which the Provenance events belong
+     * @param componentId the ID of the component to which the Data belongs
      *
      * @return the Authorizable that can be use to authorize access to provenance events
      * @throws ResourceNotFoundException if no component can be found with the given ID
      */
-    Authorizable createProvenanceAuthorizable(String componentId);
+    Authorizable createDataAuthorizable(String componentId);
 
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/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 f571c32..99672b6 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
@@ -276,6 +276,9 @@ public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
 
         // grant the user read access to the root process group resource
         if (rootGroupId != null) {
+            addAccessPolicy(authorizations, ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), READ_CODE);
+            addAccessPolicy(authorizations, ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), WRITE_CODE);
+
             addAccessPolicy(authorizations, ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), READ_CODE);
             addAccessPolicy(authorizations, ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), WRITE_CODE);
         }
@@ -322,6 +325,12 @@ public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
             // grant access to the proxy resource
             addAccessPolicy(authorizations, ResourceType.Proxy.getValue(), jaxbNodeUser.getIdentifier(), READ_CODE);
             addAccessPolicy(authorizations, ResourceType.Proxy.getValue(), jaxbNodeUser.getIdentifier(), WRITE_CODE);
+
+            // grant the user read/write access data of the root group
+            if (rootGroupId != null) {
+                addAccessPolicy(authorizations, ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, jaxbNodeUser.getIdentifier(), READ_CODE);
+                addAccessPolicy(authorizations, ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, jaxbNodeUser.getIdentifier(), WRITE_CODE);
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/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
index c8a0f53..867423e 100644
--- 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
@@ -63,7 +63,7 @@ public final class RoleAccessPolicy {
         final Set<RoleAccessPolicy> provenancePolicies = new HashSet<>();
         provenancePolicies.add(new RoleAccessPolicy(ResourceType.Provenance.getValue(), READ_ACTION));
         if (rootGroupId != null) {
-            provenancePolicies.add(new RoleAccessPolicy(ResourceType.ProvenanceEvent.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
+            provenancePolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
         }
         roleAccessPolicies.put(Role.ROLE_PROVENANCE, Collections.unmodifiableSet(provenancePolicies));
 
@@ -75,6 +75,8 @@ public final class RoleAccessPolicy {
         if (rootGroupId != null) {
             dfmPolicies.add(new RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
             dfmPolicies.add(new RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, WRITE_ACTION));
+            dfmPolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
+            dfmPolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, WRITE_ACTION));
         }
         roleAccessPolicies.put(Role.ROLE_DFM, Collections.unmodifiableSet(dfmPolicies));
 
@@ -93,6 +95,10 @@ public final class RoleAccessPolicy {
         final Set<RoleAccessPolicy> proxyPolicies = new HashSet<>();
         proxyPolicies.add(new RoleAccessPolicy(ResourceType.Proxy.getValue(), READ_ACTION));
         proxyPolicies.add(new RoleAccessPolicy(ResourceType.Proxy.getValue(), WRITE_ACTION));
+        if (rootGroupId != null) {
+            proxyPolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
+            proxyPolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, WRITE_ACTION));
+        }
         roleAccessPolicies.put(Role.ROLE_PROXY, Collections.unmodifiableSet(proxyPolicies));
 
         final Set<RoleAccessPolicy> nifiPolicies = new HashSet<>();

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/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 d1cf0c4..e5d6a54 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
@@ -254,7 +254,7 @@ public class FileAuthorizerTest {
 
         // verify user3's policies
         final Map<String,Set<RequestAction>> user3Policies = getResourceActions(policies, user3);
-        assertEquals(4, user3Policies.size());
+        assertEquals(5, user3Policies.size());
 
         assertTrue(user3Policies.containsKey(ResourceType.Flow.getValue()));
         assertEquals(1, user3Policies.get(ResourceType.Flow.getValue()).size());
@@ -286,7 +286,7 @@ public class FileAuthorizerTest {
 
         // verify user5's policies
         final Map<String,Set<RequestAction>> user5Policies = getResourceActions(policies, user5);
-        assertEquals(1, user5Policies.size());
+        assertEquals(2, user5Policies.size());
 
         assertTrue(user5Policies.containsKey(ResourceType.Proxy.getValue()));
         assertEquals(2, user5Policies.get(ResourceType.Proxy.getValue()).size());
@@ -384,7 +384,7 @@ public class FileAuthorizerTest {
         assertEquals(adminIdentity, adminUser.getIdentity());
 
         final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
-        assertEquals(9, policies.size());
+        assertEquals(11, policies.size());
 
         final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java
index 08583e1..041b982 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java
@@ -16,12 +16,33 @@
  */
 package org.apache.nifi.authorization.resource;
 
+import org.apache.nifi.authorization.AccessDeniedException;
+import org.apache.nifi.authorization.AuthorizationResult;
+import org.apache.nifi.authorization.AuthorizationResult.Result;
+import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.Resource;
+import org.apache.nifi.authorization.user.NiFiUser;
+
+import java.util.Map;
 
 /**
  * Authorizable for policies of an Authorizable.
  */
-public class AccessPolicyAuthorizable implements Authorizable {
+public class AccessPolicyAuthorizable implements Authorizable, EnforcePolicyPermissionsThroughBaseResource {
+
+    private static final Authorizable POLICIES_AUTHORIZABLE = new Authorizable() {
+        @Override
+        public Authorizable getParentAuthorizable() {
+            return null;
+        }
+
+        @Override
+        public Resource getResource() {
+            return ResourceFactory.getPoliciesResource();
+        }
+    };
+
     final Authorizable authorizable;
 
     public AccessPolicyAuthorizable(Authorizable authorizable) {
@@ -29,26 +50,73 @@ public class AccessPolicyAuthorizable implements Authorizable {
     }
 
     @Override
+    public Authorizable getBaseAuthorizable() {
+        return authorizable;
+    }
+
+    @Override
     public Authorizable getParentAuthorizable() {
-        if (authorizable.getParentAuthorizable() == null) {
-            return new Authorizable() {
-                @Override
-                public Authorizable getParentAuthorizable() {
-                    return null;
-                }
-
-                @Override
-                public Resource getResource() {
-                    return ResourceFactory.getPoliciesResource();
-                }
-            };
+        final Authorizable effectiveAuthorizable = getEffectiveAuthorizable();
+        if (effectiveAuthorizable.getParentAuthorizable() == null) {
+            return POLICIES_AUTHORIZABLE;
         } else {
-            return new AccessPolicyAuthorizable(authorizable.getParentAuthorizable());
+            return new AccessPolicyAuthorizable(effectiveAuthorizable.getParentAuthorizable());
         }
     }
 
     @Override
     public Resource getResource() {
-        return ResourceFactory.getPolicyResource(authorizable.getResource());
+        return ResourceFactory.getPolicyResource(getEffectiveAuthorizable().getResource());
+    }
+
+    private Authorizable getEffectiveAuthorizable() {
+        // possibly consider the base resource if the authorizable uses it to enforce policy permissions
+        if (authorizable instanceof EnforcePolicyPermissionsThroughBaseResource) {
+            final Authorizable baseAuthorizable = ((EnforcePolicyPermissionsThroughBaseResource) authorizable).getBaseAuthorizable();
+
+            // if the base authorizable is for a policy, we don't want to use the base otherwise it would keep unwinding and would eventually
+            // evaluate to the policy of the component and not the policy of the policies for the component
+            if (baseAuthorizable instanceof AccessPolicyAuthorizable) {
+                return authorizable;
+            } else {
+                return baseAuthorizable;
+            }
+        } else {
+            return authorizable;
+        }
+    }
+
+    @Override
+    public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
+        if (user == null) {
+            throw new AccessDeniedException("Unknown user");
+        }
+
+        final AuthorizationResult resourceResult = Authorizable.super.checkAuthorization(authorizer, action, user, resourceContext);
+
+        // if we're denied from the resource try inheriting
+        if (Result.Denied.equals(resourceResult.getResult())) {
+            return getParentAuthorizable().checkAuthorization(authorizer, action, user, resourceContext);
+        } else {
+            return resourceResult;
+        }
+    }
+
+    @Override
+    public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
+        if (user == null) {
+            throw new AccessDeniedException("Unknown user");
+        }
+
+        try {
+            Authorizable.super.authorize(authorizer, action, user, resourceContext);
+        } catch (final AccessDeniedException resourceDenied) {
+            // if we're denied from the resource try inheriting
+            try {
+                getParentAuthorizable().authorize(authorizer, action, user, resourceContext);
+            } catch (final AccessDeniedException policiesDenied) {
+                throw resourceDenied;
+            }
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataAuthorizable.java
new file mode 100644
index 0000000..cb0d0f1
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataAuthorizable.java
@@ -0,0 +1,125 @@
+/*
+ * 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.resource;
+
+import org.apache.nifi.authorization.AccessDeniedException;
+import org.apache.nifi.authorization.AuthorizationResult;
+import org.apache.nifi.authorization.AuthorizationResult.Result;
+import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.RequestAction;
+import org.apache.nifi.authorization.Resource;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserUtils;
+import org.apache.nifi.authorization.user.StandardNiFiUser;
+import org.apache.nifi.web.ResourceNotFoundException;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Authorizable for authorizing access to data. Data based authorizable requires authorization for the entire DN chain.
+ */
+public class DataAuthorizable implements Authorizable, EnforcePolicyPermissionsThroughBaseResource {
+    final Authorizable authorizable;
+
+    public DataAuthorizable(final Authorizable authorizable) {
+        this.authorizable = authorizable;
+    }
+
+    @Override
+    public Authorizable getBaseAuthorizable() {
+        return authorizable;
+    }
+
+    @Override
+    public Authorizable getParentAuthorizable() {
+        if (authorizable.getParentAuthorizable() == null) {
+            return null;
+        } else {
+            return new DataAuthorizable(authorizable.getParentAuthorizable());
+        }
+    }
+
+    @Override
+    public Resource getResource() {
+        return ResourceFactory.getDataResource(authorizable.getResource());
+    }
+
+    @Override
+    public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
+        if (user == null) {
+            return AuthorizationResult.denied("Unknown user");
+        }
+
+        AuthorizationResult result = null;
+
+        // calculate the dn chain
+        final List<String> dnChain = NiFiUserUtils.buildProxiedEntitiesChain(user);
+        for (final String identity : dnChain) {
+            try {
+                final String clientAddress = user.getIdentity().equals(identity) ? user.getClientAddress() : null;
+                final NiFiUser chainUser = new StandardNiFiUser(identity, clientAddress) {
+                    @Override
+                    public boolean isAnonymous() {
+                        // allow current user to drive anonymous flag as anonymous users are never chained... supports single user case
+                        return user.isAnonymous();
+                    }
+                };
+
+                result = Authorizable.super.checkAuthorization(authorizer, action, chainUser, resourceContext);
+            } catch (final ResourceNotFoundException e) {
+                result = AuthorizationResult.denied("Unknown source component.");
+            }
+
+            if (!Result.Approved.equals(result.getResult())) {
+                break;
+            }
+        }
+
+        if (result == null) {
+            result = AuthorizationResult.denied();
+        }
+
+        return result;
+    }
+
+    @Override
+    public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
+        if (user == null) {
+            throw new AccessDeniedException("Unknown user");
+        }
+
+        // calculate the dn chain
+        final List<String> dnChain = NiFiUserUtils.buildProxiedEntitiesChain(user);
+        for (final String identity : dnChain) {
+            try {
+                final String clientAddress = user.getIdentity().equals(identity) ? user.getClientAddress() : null;
+                final NiFiUser chainUser = new StandardNiFiUser(identity, clientAddress) {
+                    @Override
+                    public boolean isAnonymous() {
+                        // allow current user to drive anonymous flag as anonymous users are never chained... supports single user case
+                        return user.isAnonymous();
+                    }
+                };
+
+                Authorizable.super.authorize(authorizer, action, chainUser, resourceContext);
+            } catch (final ResourceNotFoundException e) {
+                throw new AccessDeniedException("Unknown source component.");
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java
index 53aecbc..21df4f8 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java
@@ -19,12 +19,13 @@ package org.apache.nifi.authorization.resource;
 import org.apache.nifi.authorization.Resource;
 
 /**
- * Authorizable for policies of an Authorizable.
+ * Authorizable for authorizing data transfers.
  */
-public class DataTransferAuthorizable implements Authorizable {
+public class DataTransferAuthorizable extends DataAuthorizable implements EnforcePolicyPermissionsThroughBaseResource {
     final Authorizable authorizable;
 
     public DataTransferAuthorizable(Authorizable authorizable) {
+        super(authorizable);
         this.authorizable = authorizable;
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java
new file mode 100644
index 0000000..115315f
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java
@@ -0,0 +1,38 @@
+/*
+ * 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.resource;
+
+/**
+ * Defers permissions on policies to the policies of the base authorizable. Required because we don't
+ * want to change the enforcement of the policies on the authorizable. For example...
+ *
+ * if a user has permissions to /policies/input-ports/1234 then they have permissions to the following
+ *
+ * - the policy for /input-ports/1234                -> /policies/input-ports/1234
+ * - the policy for /data/input-ports/1234           -> /policies/data/input-ports/1234
+ * - the policy for /data-transfers/input-ports/1234 -> /policies/data-transfers/input-ports/1234
+ * - the policy for /policies/input-ports/1234       -> /policies/policies/input-ports/1234
+ */
+public interface EnforcePolicyPermissionsThroughBaseResource {
+
+    /**
+     * Returns the base authorizable. Cannot be null.
+     *
+     * @return base authorizable
+     */
+    Authorizable getBaseAuthorizable();
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceEventAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceEventAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceEventAuthorizable.java
deleted file mode 100644
index 153047e..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceEventAuthorizable.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.authorization.resource;
-
-import org.apache.nifi.authorization.Resource;
-
-public class ProvenanceEventAuthorizable implements Authorizable {
-    final Authorizable authorizable;
-
-    public ProvenanceEventAuthorizable(final Authorizable authorizable) {
-        this.authorizable = authorizable;
-    }
-
-    @Override
-    public Authorizable getParentAuthorizable() {
-        if (authorizable.getParentAuthorizable() == null) {
-            return null;
-        } else {
-            return new ProvenanceEventAuthorizable(authorizable.getParentAuthorizable());
-        }
-    }
-
-    @Override
-    public Resource getResource() {
-        return ResourceFactory.getProvenanceEventResource(authorizable.getResource());
-    }
-}

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/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 baa58ac..426e7fd 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
@@ -166,15 +166,15 @@ public final class ResourceFactory {
         }
     };
 
-    private final static Resource PROVENANCE_EVENT_RESOURCE = new Resource() {
+    private final static Resource DATA_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
-            return ResourceType.ProvenanceEvent.getValue();
+            return ResourceType.Data.getValue();
         }
 
         @Override
         public String getName() {
-            return "Provenance Event";
+            return "Data";
         }
     };
 
@@ -567,16 +567,16 @@ public final class ResourceFactory {
      * @param resource The resource for the component being accessed
      * @return The resource for the provenance of the component being accessed
      */
-    public static Resource getProvenanceEventResource(final Resource resource) {
+    public static Resource getDataResource(final Resource resource) {
         return new Resource() {
             @Override
             public String getIdentifier() {
-                return String.format("%s%s", PROVENANCE_EVENT_RESOURCE.getIdentifier(), resource.getIdentifier());
+                return String.format("%s%s", DATA_RESOURCE.getIdentifier(), resource.getIdentifier());
             }
 
             @Override
             public String getName() {
-                return "Provenance Events for " + resource.getName();
+                return "Data for " + resource.getName();
             }
         };
     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/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 bce270a..37fe018 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
@@ -29,7 +29,7 @@ public enum ResourceType {
     Processor("/processors"),
     ProcessGroup("/process-groups"),
     Provenance("/provenance"),
-    ProvenanceEvent("/provenance-events"),
+    Data("/data"),
     Proxy("/proxy"),
     RemoteProcessGroup("/remote-process-groups"),
     ReportingTask("/reporting-tasks"),

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
index 4a75274..6a4776a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
@@ -20,6 +20,9 @@ import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Utility methods for retrieving information about the current application user.
  *
@@ -56,4 +59,27 @@ public final class NiFiUserUtils {
             return user.getIdentity();
         }
     }
+
+    /**
+     * Builds the proxy chain for the specified user.
+     *
+     * @param user The current user
+     * @return The proxy chain for that user in List form
+     */
+    public static List<String> buildProxiedEntitiesChain(final NiFiUser user) {
+        // calculate the dn chain
+        final List<String> proxyChain = new ArrayList<>();
+
+        // build the dn chain
+        NiFiUser chainedUser = user;
+        do {
+            // add the entry for this user
+            proxyChain.add(chainedUser.getIdentity());
+
+            // go to the next user in the chain
+            chainedUser = chainedUser.getChain();
+        } while (chainedUser != null);
+
+        return proxyChain;
+    }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
index ecc9e6f..86a9f38 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
@@ -158,20 +158,26 @@ public class Template implements Authorizable {
     }
 
     @Override
-    public void authorize(final Authorizer authorizer, final RequestAction action, final NiFiUser user) throws AccessDeniedException {
-        final AuthorizationResult result = checkAuthorization(authorizer, action, true, user);
-        if (Result.Denied.equals(result)) {
+    public void authorize(final Authorizer authorizer, final RequestAction action, final NiFiUser user, final Map<String, String> resourceContext) throws AccessDeniedException {
+        final AuthorizationResult result = checkAuthorization(authorizer, action, true, user, resourceContext);
+        if (Result.Denied.equals(result.getResult())) {
             final String explanation = result.getExplanation() == null ? "Access is denied" : result.getExplanation();
             throw new AccessDeniedException(explanation);
         }
     }
 
     @Override
-    public AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final NiFiUser user) {
-        return checkAuthorization(authorizer, action, false, user);
+    public AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final NiFiUser user, final Map<String, String> resourceContext) {
+        return checkAuthorization(authorizer, action, false, user, resourceContext);
     }
 
-    private AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final boolean accessAttempt, final NiFiUser user) {
+    private AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final boolean accessAttempt,
+                                                   final NiFiUser user, final Map<String, String> resourceContext) {
+
+        if (user == null) {
+            return AuthorizationResult.denied("Unknown user");
+        }
+
         final Map<String,String> userContext;
         if (!StringUtils.isBlank(user.getClientAddress())) {
             userContext = new HashMap<>();
@@ -188,6 +194,7 @@ public class Template implements Authorizable {
             .action(action)
             .resource(getResource())
             .userContext(userContext)
+            .resourceContext(resourceContext)
             .build();
 
         // perform the authorization

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java
index 3745d7d..f77288a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java
@@ -139,6 +139,10 @@ public final class StandardConnection implements Connection {
 
     @Override
     public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
+        if (user == null) {
+            return AuthorizationResult.denied("Unknown user");
+        }
+
         // check the source
         final AuthorizationResult sourceResult = getSource().checkAuthorization(authorizer, action, user, resourceContext);
         if (Result.Denied.equals(sourceResult.getResult())) {
@@ -151,6 +155,10 @@ public final class StandardConnection implements Connection {
 
     @Override
     public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
+        if (user == null) {
+            throw new AccessDeniedException("Unknown user");
+        }
+
         getSource().authorize(authorizer, action, user, resourceContext);
         getDestination().authorize(authorizer, action, user, resourceContext);
     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
index 30e382d..5de77f6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
@@ -18,38 +18,6 @@ package org.apache.nifi.controller;
 
 import com.sun.jersey.api.client.ClientHandlerException;
 import org.apache.commons.collections4.Predicate;
-import static java.util.Objects.requireNonNull;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import javax.net.ssl.SSLContext;
-
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.action.Action;
 import org.apache.nifi.admin.service.AuditService;
@@ -63,7 +31,7 @@ import org.apache.nifi.authorization.Authorizer;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.Resource;
 import org.apache.nifi.authorization.resource.Authorizable;
-import org.apache.nifi.authorization.resource.ProvenanceEventAuthorizable;
+import org.apache.nifi.authorization.resource.DataAuthorizable;
 import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.cluster.HeartbeatPayload;
@@ -238,6 +206,37 @@ import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.net.ssl.SSLContext;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import static java.util.Objects.requireNonNull;
+
 
 public class FlowController implements EventAccess, ControllerServiceProvider, ReportingTaskProvider, QueueProvider, Authorizable, ProvenanceAuthorizableFactory, NodeTypeProvider {
 
@@ -3902,15 +3901,15 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
     }
 
     @Override
-    public Authorizable createProvenanceAuthorizable(final String componentId) {
+    public Authorizable createDataAuthorizable(final String componentId) {
         final String rootGroupId = getRootGroupId();
 
         // Provenance Events are generated only by connectable components, with the exception of DOWNLOAD events,
         // which have the root process group's identifier assigned as the component ID. So, we check if the component ID
         // is set to the root group and otherwise assume that the ID is that of a component.
-        final ProvenanceEventAuthorizable authorizable;
+        final DataAuthorizable authorizable;
         if (rootGroupId.equals(componentId)) {
-            authorizable = new ProvenanceEventAuthorizable(rootGroup);
+            authorizable = new DataAuthorizable(rootGroup);
         } else {
             final Connectable connectable = rootGroup.findConnectable(componentId);
 
@@ -3918,7 +3917,7 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
                 throw new ResourceNotFoundException("The component that generated this event is no longer part of the data flow.");
             }
 
-            authorizable = new ProvenanceEventAuthorizable(connectable);
+            authorizable = new DataAuthorizable(connectable);
         }
 
         return authorizable;

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
index e0faafb..bc958c3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
@@ -180,6 +180,13 @@ public interface AuthorizableLookup {
     Authorizable getTenant();
 
     /**
+     * Get the authorizable for data of a specified component.
+     *
+     * @return authorizable
+     */
+    Authorizable getData(String id);
+
+    /**
      * Get the authorizable for access all policies.
      *
      * @return authorizable

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
index c0805c0..1e3c03a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
@@ -20,7 +20,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.resource.AccessPolicyAuthorizable;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.resource.DataTransferAuthorizable;
-import org.apache.nifi.authorization.resource.ProvenanceEventAuthorizable;
+import org.apache.nifi.authorization.resource.DataAuthorizable;
 import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.resource.ResourceType;
 import org.apache.nifi.authorization.resource.TenantAuthorizable;
@@ -234,6 +234,11 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
+    public Authorizable getData(final String id) {
+        return controllerFacade.getDataAuthorizable(id);
+    }
+
+    @Override
     public Authorizable getPolicies() {
         return POLICIES_AUTHORIZABLE;
     }
@@ -269,7 +274,7 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
         }
 
         // if this is a policy or a provenance event resource, there should be another resource type
-        if (ResourceType.Policy.equals(resourceType) || ResourceType.ProvenanceEvent.equals(resourceType) || ResourceType.DataTransfer.equals(resourceType)) {
+        if (ResourceType.Policy.equals(resourceType) || ResourceType.Data.equals(resourceType) || ResourceType.DataTransfer.equals(resourceType)) {
             final ResourceType primaryResourceType = resourceType;
 
             // get the resource type
@@ -288,8 +293,8 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
             // must either be a policy, event, or data transfer
             if (ResourceType.Policy.equals(primaryResourceType)) {
                 return new AccessPolicyAuthorizable(getAccessPolicy(resourceType, resource));
-            } else if (ResourceType.ProvenanceEvent.equals(primaryResourceType)) {
-                return new ProvenanceEventAuthorizable(getAccessPolicy(resourceType, resource));
+            } else if (ResourceType.Data.equals(primaryResourceType)) {
+                return new DataAuthorizable(getAccessPolicy(resourceType, resource));
             } else {
                 return new DataTransferAuthorizable(getAccessPolicy(resourceType, resource));
             }
@@ -340,8 +345,8 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
             case Template:
                 authorizable = getTemplate(componentId);
                 break;
-            case ProvenanceEvent:
-                authorizable = controllerFacade.getProvenanceEventAuthorizable(componentId);
+            case Data:
+                authorizable = controllerFacade.getDataAuthorizable(componentId);
                 break;
         }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
index 1786bce..e17b147 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
@@ -164,20 +164,12 @@ public class StandardNiFiContentAccess implements ContentAccess {
     }
 
     private DownloadableContent getFlowFileContent(final String connectionId, final String flowfileId, final String dataUri) {
-        // TODO - ensure the user is authorized - not checking with @PreAuthorized annotation as aspect not trigger on call within a class
-//        if (!NiFiUserUtils.getAuthorities().contains(Authority.ROLE_DFM.toString())) {
-//            throw new AccessDeniedException("Access is denied.");
-//        }
-
+        // user authorization is handled once we have the actual content so we can utilize the flow file attributes in the resource context
         return serviceFacade.getContent(connectionId, flowfileId, dataUri);
     }
 
     private DownloadableContent getProvenanceEventContent(final Long eventId, final String dataUri, final ContentDirection direction) {
-        // TODO - ensure the user is authorized - not checking with @PreAuthorized annotation as aspect not trigger on call within a class
-//        if (!NiFiUserUtils.getAuthorities().contains(Authority.ROLE_PROVENANCE.toString())) {
-//            throw new AccessDeniedException("Access is denied.");
-//        }
-
+        // user authorization is handled once we have the actual prov event so we can utilize the event attributes in the resource context
         return serviceFacade.getContent(eventId, dataUri, direction);
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index 6186bf1..b2b93db 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -37,6 +37,7 @@ import org.apache.nifi.authorization.Resource;
 import org.apache.nifi.authorization.User;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.resource.DataTransferAuthorizable;
+import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.cluster.coordination.ClusterCoordinator;
@@ -850,8 +851,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final Connection connection = connectionDAO.getConnection(connectionId);
         final ConnectionDTO snapshot = deleteComponent(
                 revision,
-                connection,
+                connection.getResource().getIdentifier(),
                 () -> connectionDAO.deleteConnection(connectionId),
+                false,
                 dtoFactory.createConnectionDto(connection));
 
         return entityFactory.createConnectionEntity(snapshot, null, null, null);
@@ -883,8 +885,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final ProcessorNode processor = processorDAO.getProcessor(processorId);
         final ProcessorDTO snapshot = deleteComponent(
                 revision,
-                processor,
+                processor.getResource().getIdentifier(),
                 () -> processorDAO.deleteProcessor(processorId),
+                true,
                 dtoFactory.createProcessorDto(processor));
 
         return entityFactory.createProcessorEntity(snapshot, null, null, null, null);
@@ -895,8 +898,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final Label label = labelDAO.getLabel(labelId);
         final LabelDTO snapshot = deleteComponent(
                 revision,
-                label,
+                label.getResource().getIdentifier(),
                 () -> labelDAO.deleteLabel(labelId),
+                true,
                 dtoFactory.createLabelDto(label));
 
         return entityFactory.createLabelEntity(snapshot, null, null);
@@ -910,21 +914,13 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final Set<AccessPolicySummaryEntity> policyEntities = user != null ? userGroupDAO.getAccessPoliciesForUser(userId).stream()
                 .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()) : null;
 
-        final RevisionClaim claim = new StandardRevisionClaim(revision);
-        final NiFiUser nifiUser = NiFiUserUtils.getNiFiUser();
-
-        // perform the deletion
-        final UserDTO snapshot = revisionManager.deleteRevision(claim, nifiUser, () -> {
-            logger.debug("Attempting to delete component {} with claim {}", user, claim);
-
-            userDAO.deleteUser(userId);
-
-            // save the flow
-            controllerFacade.save();
-            logger.debug("Deletion of component {} was successful", user);
-
-            return dtoFactory.createUserDto(user, userGroups, policyEntities);
-        });
+        final String resourceIdentifier = ResourceFactory.getTenantResource().getIdentifier() + "/" + userId;
+        final UserDTO snapshot = deleteComponent(
+                revision,
+                resourceIdentifier,
+                () -> userDAO.deleteUser(userId),
+                false, // no user specific policies to remove
+                dtoFactory.createUserDto(user, userGroups, policyEntities));
 
         return entityFactory.createUserEntity(snapshot, null, null);
     }
@@ -936,21 +932,13 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
                 .map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) :
                 null;
 
-        final RevisionClaim claim = new StandardRevisionClaim(revision);
-        final NiFiUser nifiUser = NiFiUserUtils.getNiFiUser();
-
-        // perform the deletion
-        final UserGroupDTO snapshot = revisionManager.deleteRevision(claim, nifiUser, () -> {
-            logger.debug("Attempting to delete component {} with claim {}", userGroup, claim);
-
-            userGroupDAO.deleteUserGroup(userGroupId);
-
-            // save the flow
-            controllerFacade.save();
-            logger.debug("Deletion of component {} was successful", userGroup);
-
-            return dtoFactory.createUserGroupDto(userGroup, users);
-        });
+        final String resourceIdentifier = ResourceFactory.getTenantResource().getIdentifier() + "/" + userGroupId;
+        final UserGroupDTO snapshot = deleteComponent(
+                revision,
+                resourceIdentifier,
+                () -> userGroupDAO.deleteUserGroup(userGroupId),
+                false, // no user group specific policies to remove
+                dtoFactory.createUserGroupDto(userGroup, users));
 
         return entityFactory.createUserGroupEntity(snapshot, null, null);
     }
@@ -962,8 +950,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final Set<TenantEntity> users = accessPolicy != null ? accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) : null;
         final AccessPolicyDTO snapshot = deleteComponent(
                 revision,
-                authorizableLookup.getAccessPolicyById(accessPolicyId),
+                accessPolicy.getResource(),
                 () -> accessPolicyDAO.deleteAccessPolicy(accessPolicyId),
+                false, // no need to clean up any policies as it's already been removed above
                 dtoFactory.createAccessPolicyDto(accessPolicy, userGroups,
                         users));
 
@@ -975,8 +964,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final Funnel funnel = funnelDAO.getFunnel(funnelId);
         final FunnelDTO snapshot = deleteComponent(
                 revision,
-                funnel,
+                funnel.getResource().getIdentifier(),
                 () -> funnelDAO.deleteFunnel(funnelId),
+                true,
                 dtoFactory.createFunnelDto(funnel));
 
         return entityFactory.createFunnelEntity(snapshot, null, null);
@@ -986,47 +976,49 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
      * Deletes a component using the Optimistic Locking Manager
      *
      * @param revision     the current revision
+     * @param resourceIdentifier the identifier of the resource being removed
      * @param deleteAction the action that deletes the component via the appropriate DAO object
+     * @param cleanUpPolicies whether or not the policies for this resource should be removed as well - not necessary when there are
+     *                        no component specific policies or if the policies of the component are inherited
      * @return a dto that represents the new configuration
      */
-    private <D, C> D deleteComponent(final Revision revision, final Authorizable authorizable, final Runnable deleteAction, final D dto) {
+    private <D, C> D deleteComponent(final Revision revision, final String resourceIdentifier, final Runnable deleteAction, final boolean cleanUpPolicies, final D dto) {
         final RevisionClaim claim = new StandardRevisionClaim(revision);
         final NiFiUser user = NiFiUserUtils.getNiFiUser();
 
         return revisionManager.deleteRevision(claim, user, new DeleteRevisionTask<D>() {
             @Override
             public D performTask() {
-                logger.debug("Attempting to delete component {} with claim {}", authorizable, claim);
+                logger.debug("Attempting to delete component {} with claim {}", resourceIdentifier, claim);
 
+                // run the delete action
                 deleteAction.run();
 
                 // save the flow
                 controllerFacade.save();
-                logger.debug("Deletion of component {} was successful", authorizable);
+                logger.debug("Deletion of component {} was successful", resourceIdentifier);
 
-                // if configured with a policy based authorizer, attempt to remove the corresponding policies
-                if (authorizer instanceof AbstractPolicyBasedAuthorizer) {
+                // clean up the policy if necessary and configured with a policy based authorizer
+                if (cleanUpPolicies && authorizer instanceof AbstractPolicyBasedAuthorizer) {
                     try {
                         // since the component is being deleted, also delete any relevant read access policies
-                        final AccessPolicy readPolicy = accessPolicyDAO.getAccessPolicy(RequestAction.READ, authorizable);
-                        if (authorizable.getResource().getIdentifier().equals(readPolicy.getResource())) {
+                        final AccessPolicy readPolicy = accessPolicyDAO.getAccessPolicy(RequestAction.READ, resourceIdentifier);
+                        if (readPolicy != null) {
                             accessPolicyDAO.deleteAccessPolicy(readPolicy.getIdentifier());
                         }
-                    } catch (final ResourceNotFoundException e) {
-                        // no policy exists for this component... no worries
                     } catch (final Exception e) {
-                        logger.warn(String.format("Unable to remove access policy for %s %s after component removal.", RequestAction.READ, authorizable.getResource().getIdentifier()), e);
+                        logger.warn(String.format("Unable to remove access policy for %s %s after component removal.", RequestAction.READ, resourceIdentifier), e);
                     }
                     try {
                         // since the component is being deleted, also delete any relevant write access policies
-                        final AccessPolicy writePolicy = accessPolicyDAO.getAccessPolicy(RequestAction.WRITE, authorizable);
-                        if (authorizable.getResource().getIdentifier().equals(writePolicy.getResource())) {
+                        final AccessPolicy writePolicy = accessPolicyDAO.getAccessPolicy(RequestAction.WRITE, resourceIdentifier);
+                        if (writePolicy != null) {
                             accessPolicyDAO.deleteAccessPolicy(writePolicy.getIdentifier());
                         }
                     } catch (final ResourceNotFoundException e) {
                         // no policy exists for this component... no worries
                     } catch (final Exception e) {
-                        logger.warn(String.format("Unable to remove access policy for %s %s after component removal.", RequestAction.WRITE, authorizable.getResource().getIdentifier()), e);
+                        logger.warn(String.format("Unable to remove access policy for %s %s after component removal.", RequestAction.WRITE, resourceIdentifier), e);
                     }
                 }
 
@@ -1071,8 +1063,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final Port port = inputPortDAO.getPort(inputPortId);
         final PortDTO snapshot = deleteComponent(
                 revision,
-                port,
+                port.getResource().getIdentifier(),
                 () -> inputPortDAO.deletePort(inputPortId),
+                true,
                 dtoFactory.createPortDto(port));
 
         return entityFactory.createPortEntity(snapshot, null, null, null, null);
@@ -1083,8 +1076,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final Port port = outputPortDAO.getPort(outputPortId);
         final PortDTO snapshot = deleteComponent(
                 revision,
-                port,
+                port.getResource().getIdentifier(),
                 () -> outputPortDAO.deletePort(outputPortId),
+                true,
                 dtoFactory.createPortDto(port));
 
         return entityFactory.createPortEntity(snapshot, null, null, null, null);
@@ -1095,8 +1089,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
         final ProcessGroupDTO snapshot = deleteComponent(
                 revision,
-                processGroup,
+                processGroup.getResource().getIdentifier(),
                 () -> processGroupDAO.deleteProcessGroup(groupId),
+                true,
                 dtoFactory.createProcessGroupDto(processGroup));
 
         return entityFactory.createProcessGroupEntity(snapshot, null, null, null, null);
@@ -1107,8 +1102,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final RemoteProcessGroup remoteProcessGroup = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupId);
         final RemoteProcessGroupDTO snapshot = deleteComponent(
                 revision,
-                remoteProcessGroup,
+                remoteProcessGroup.getResource().getIdentifier(),
                 () -> remoteProcessGroupDAO.deleteRemoteProcessGroup(remoteProcessGroupId),
+                true,
                 dtoFactory.createRemoteProcessGroupDto(remoteProcessGroup));
 
         return entityFactory.createRemoteProcessGroupEntity(snapshot, null, null, null, null);
@@ -1740,8 +1736,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final ControllerServiceNode controllerService = controllerServiceDAO.getControllerService(controllerServiceId);
         final ControllerServiceDTO snapshot = deleteComponent(
                 revision,
-                controllerService,
+                controllerService.getResource().getIdentifier(),
                 () -> controllerServiceDAO.deleteControllerService(controllerServiceId),
+                true,
                 dtoFactory.createControllerServiceDto(controllerService));
 
         return entityFactory.createControllerServiceEntity(snapshot, null, null, null);
@@ -1793,8 +1790,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final ReportingTaskNode reportingTask = reportingTaskDAO.getReportingTask(reportingTaskId);
         final ReportingTaskDTO snapshot = deleteComponent(
                 revision,
-                reportingTask,
+                reportingTask.getResource().getIdentifier(),
                 () -> reportingTaskDAO.deleteReportingTask(reportingTaskId),
+                true,
                 dtoFactory.createReportingTaskDto(reportingTask));
 
         return entityFactory.createReportingTaskEntity(snapshot, null, null, null);

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java
index c77ed65..8a03dbf 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java
@@ -83,9 +83,7 @@ public class AccessPolicyResource extends ApplicationResource {
      * @return accessPolicyEntity
      */
     public AccessPolicyEntity populateRemainingAccessPolicyEntityContent(AccessPolicyEntity accessPolicyEntity) {
-        if (accessPolicyEntity.getComponent() != null) {
-            accessPolicyEntity.setUri(generateResourceUri("policies", accessPolicyEntity.getId()));
-        }
+        accessPolicyEntity.setUri(generateResourceUri("policies", accessPolicyEntity.getId()));
         return accessPolicyEntity;
     }
 
@@ -229,7 +227,7 @@ public class AccessPolicyResource extends ApplicationResource {
         }
 
         // set the access policy id as appropriate
-        accessPolicyEntity.getComponent().setId(generateUuid());
+        requestAccessPolicy.setId(generateUuid());
 
         // get revision from the config
         final RevisionDTO revisionDTO = accessPolicyEntity.getRevision();
@@ -286,7 +284,7 @@ public class AccessPolicyResource extends ApplicationResource {
         // authorize access
         serviceFacade.authorizeAccess(lookup -> {
             Authorizable authorizable  = lookup.getAccessPolicyById(id);
-            authorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+            authorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
         });
 
         // get the access policy
@@ -438,7 +436,7 @@ public class AccessPolicyResource extends ApplicationResource {
                 revision,
                 lookup -> {
                     final Authorizable accessPolicy = lookup.getAccessPolicyById(id);
-                    accessPolicy.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
+                    accessPolicy.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                 },
                 () -> {
                 },