You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2016/12/15 19:34:04 UTC

[5/6] nifi git commit: NIFI-3133: - Ensuring that Remote Group Ports are always authorized according to their Remote Process Group.

NIFI-3133: - Ensuring that Remote Group Ports are always authorized according to their Remote Process Group.

NIFI-3133:
- Using getSourceAuthorizable() when accessing flow files and content.

NIFI-3133:
- Decouple local and remote connectable's to avoid ambiguity with self referencing RPGs.

NIFI-3133:
- Addressing comments from the PR.

NIFI-3133:
- Fixed check verifying source/destination when creating a connection.

NIFI-3133:
- Only showing the go to link when the source component is not a remote port.

NIFI-3133:
- Removing unnecessary checking of remote group port authorization since it's handled by the parent RPG.

NIFI-3133:
- Fixing issue showing the connection details dialog when the source component is a RPG.

NIFI-3133:
- Ensuring the local connectable was found.

This closes #1297

Signed-off-by: jpercivall <JP...@apache.org>


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

Branch: refs/heads/support/nifi-1.1.x
Commit: b917e9be36b84bd21915ceb7a9bf103b5ee2787e
Parents: 582fd0c
Author: Matt Gilman <ma...@gmail.com>
Authored: Mon Dec 5 11:15:29 2016 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Thu Dec 15 14:14:41 2016 -0500

----------------------------------------------------------------------
 .../nifi/provenance/ProvenanceEventRecord.java  |  11 ++
 .../ProvenanceAuthorizableFactory.java          |  11 +-
 .../org/apache/nifi/connectable/Connection.java |  12 ++-
 .../org/apache/nifi/groups/ProcessGroup.java    |  12 ++-
 .../nifi/connectable/StandardConnection.java    |  62 ++++++++---
 .../apache/nifi/controller/FlowController.java  |  19 +++-
 .../reporting/StandardReportingContext.java     |  12 +--
 .../repository/StandardProcessSession.java      |  54 +++++-----
 .../nifi/groups/StandardProcessGroup.java       |  27 +++--
 .../service/mock/MockProcessGroup.java          |   8 +-
 .../nifi/authorization/AuthorizableLookup.java  |  29 +-----
 .../authorization/ConnectionAuthorizable.java   |  14 +++
 .../StandardAuthorizableLookup.java             |  41 ++++----
 .../apache/nifi/web/api/ConnectionResource.java |  31 +++++-
 .../nifi/web/api/FlowFileQueueResource.java     |  12 +--
 .../org/apache/nifi/web/api/FlowResource.java   |   2 +-
 .../nifi/web/api/ProcessGroupResource.java      |  43 +++++++-
 .../web/api/RemoteProcessGroupResource.java     |   8 +-
 .../nifi/web/controller/ControllerFacade.java   |  71 ++++++++-----
 .../web/dao/impl/StandardConnectionDAO.java     |  32 ++++--
 .../web/dao/impl/StandardProcessGroupDAO.java   |   4 +-
 .../main/webapp/js/nf/nf-connection-details.js  |   2 +
 .../js/nf/provenance/nf-provenance-table.js     |   3 +-
 .../PersistentProvenanceRepository.java         | 103 ++++++++++---------
 .../VolatileProvenanceRepository.java           |  13 ++-
 25 files changed, 417 insertions(+), 219 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-api/src/main/java/org/apache/nifi/provenance/ProvenanceEventRecord.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/provenance/ProvenanceEventRecord.java b/nifi-api/src/main/java/org/apache/nifi/provenance/ProvenanceEventRecord.java
index eaa3464..7ba1622 100644
--- a/nifi-api/src/main/java/org/apache/nifi/provenance/ProvenanceEventRecord.java
+++ b/nifi-api/src/main/java/org/apache/nifi/provenance/ProvenanceEventRecord.java
@@ -24,6 +24,9 @@ import java.util.Map;
  */
 public interface ProvenanceEventRecord {
 
+    String REMOTE_INPUT_PORT_TYPE = "Remote Input Port";
+    String REMOTE_OUTPUT_PORT_TYPE = "Remote Output Port";
+
     /**
      * @return a unique ID for this Provenance Event. Depending on the
      * implementation, the Event ID may be set to -1 until the event has been
@@ -101,6 +104,14 @@ public interface ProvenanceEventRecord {
     String getComponentType();
 
     /**
+     * @return whether this event originated from a remote group port
+     */
+    default boolean isRemotePortType() {
+        final String componentType = getComponentType();
+        return REMOTE_INPUT_PORT_TYPE.equals(componentType) || REMOTE_OUTPUT_PORT_TYPE.equals(componentType);
+    }
+
+    /**
      * @return a URI that provides information about the System and Protocol
      * information over which the transfer occurred. The intent of this field is
      * such that both the sender and the receiver can publish the events to an

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 9699041..0bbb190 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
@@ -31,6 +31,15 @@ public interface ProvenanceAuthorizableFactory {
      * @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 createDataAuthorizable(String componentId);
+    Authorizable createLocalDataAuthorizable(String componentId);
+
+    /**
+     * Generates an Authorizable object for the Data of the remote group port with the given ID.
+     *
+     * @param remoteGroupPortId the ID of the remote group port to which the data belongs
+     * @return the Authorizable that can be used to authorize access to provenance events
+     * @throws ResourceNotFoundException if no component can be found with the given ID
+     */
+    Authorizable createRemoteDataAuthorizable(String remoteGroupPortId);
 
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connection.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connection.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connection.java
index 1d240b5..f0d2e91 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connection.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connection.java
@@ -16,10 +16,6 @@
  */
 package org.apache.nifi.connectable;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.controller.queue.FlowFileQueue;
 import org.apache.nifi.controller.repository.FlowFileRecord;
@@ -27,6 +23,10 @@ import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.processor.FlowFileFilter;
 import org.apache.nifi.processor.Relationship;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
 public interface Connection extends Authorizable {
 
     void enqueue(FlowFileRecord flowFile);
@@ -35,6 +35,8 @@ public interface Connection extends Authorizable {
 
     Connectable getDestination();
 
+    Authorizable getDestinationAuthorizable();
+
     Collection<Relationship> getRelationships();
 
     FlowFileQueue getFlowFileQueue();
@@ -59,6 +61,8 @@ public interface Connection extends Authorizable {
 
     Connectable getSource();
 
+    Authorizable getSourceAuthorizable();
+
     void setRelationships(Collection<Relationship> newRelationships);
 
     void setDestination(final Connectable newDestination);

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java
index be0bcd3..122e454 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java
@@ -30,6 +30,7 @@ import org.apache.nifi.controller.label.Label;
 import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.flowfile.FlowFile;
 import org.apache.nifi.processor.Processor;
+import org.apache.nifi.remote.RemoteGroupPort;
 
 import java.util.Collection;
 import java.util.List;
@@ -731,9 +732,16 @@ public interface ProcessGroup extends ComponentAuthorizable, Positionable {
      * @param identifier of connectable
      * @return the Connectable with the given ID, if it exists; otherwise
      * returns null. This performs a recursive search of all ProcessGroups'
-     * input ports, output ports, funnels, processors, and remote process groups
+     * input ports, output ports, funnels, processors
      */
-    Connectable findConnectable(String identifier);
+    Connectable findLocalConnectable(String identifier);
+
+    /**
+     * @param identifier of remote group port
+     * @return the RemoteGroupPort with the given ID, if it exists; otherwise
+     * returns null.
+     */
+    RemoteGroupPort findRemoteGroupPort(String identifier);
 
     /**
      * @return a Set of all {@link org.apache.nifi.connectable.Positionable}s contained within this

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 6d22281..3d5efed 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
@@ -16,17 +16,6 @@
  */
 package org.apache.nifi.connectable;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.builder.EqualsBuilder;
@@ -51,6 +40,19 @@ import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.processor.FlowFileFilter;
 import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.provenance.ProvenanceEventRepository;
+import org.apache.nifi.remote.RemoteGroupPort;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
 
 /**
  * Models a connection between connectable components. A connection may contain
@@ -138,19 +140,49 @@ public final class StandardConnection implements Connection {
     }
 
     @Override
+    public Authorizable getSourceAuthorizable() {
+        final Connectable sourceConnectable = getSource();
+        final Authorizable sourceAuthorizable;
+
+        // if the source is a remote group port, authorize according to the RPG
+        if (sourceConnectable instanceof RemoteGroupPort) {
+            sourceAuthorizable = ((RemoteGroupPort) sourceConnectable).getRemoteProcessGroup();
+        } else {
+            sourceAuthorizable = sourceConnectable;
+        }
+
+        return sourceAuthorizable;
+    }
+
+    @Override
+    public Authorizable getDestinationAuthorizable() {
+        final Connectable destinationConnectable = getDestination();
+        final Authorizable destinationAuthorizable;
+
+        // if the destination is a remote group port, authorize according to the RPG
+        if (destinationConnectable instanceof RemoteGroupPort) {
+            destinationAuthorizable = ((RemoteGroupPort) destinationConnectable).getRemoteProcessGroup();
+        } else {
+            destinationAuthorizable = destinationConnectable;
+        }
+
+        return destinationAuthorizable;
+    }
+
+    @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);
+        final AuthorizationResult sourceResult = getSourceAuthorizable().checkAuthorization(authorizer, action, user, resourceContext);
         if (Result.Denied.equals(sourceResult.getResult())) {
             return sourceResult;
         }
 
         // check the destination
-        return getDestination().checkAuthorization(authorizer, action, user, resourceContext);
+        return getDestinationAuthorizable().checkAuthorization(authorizer, action, user, resourceContext);
     }
 
     @Override
@@ -159,8 +191,8 @@ public final class StandardConnection implements Connection {
             throw new AccessDeniedException("Unknown user");
         }
 
-        getSource().authorize(authorizer, action, user, resourceContext);
-        getDestination().authorize(authorizer, action, user, resourceContext);
+        getSourceAuthorizable().authorize(authorizer, action, user, resourceContext);
+        getDestinationAuthorizable().authorize(authorizer, action, user, resourceContext);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 adab649..17c2f61 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
@@ -4006,7 +4006,7 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
     }
 
     @Override
-    public Authorizable createDataAuthorizable(final String componentId) {
+    public Authorizable createLocalDataAuthorizable(final String componentId) {
         final String rootGroupId = getRootGroupId();
 
         // Provenance Events are generated only by connectable components, with the exception of DOWNLOAD events,
@@ -4018,7 +4018,7 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
             authorizable = new DataAuthorizable(getRootGroup());
         } else {
             // check if the component is a connectable, this should be the case most often
-            final Connectable connectable = getRootGroup().findConnectable(componentId);
+            final Connectable connectable = getRootGroup().findLocalConnectable(componentId);
             if (connectable == null) {
                 // if the component id is not a connectable then consider a connection
                 final Connection connection = getRootGroup().findConnection(componentId);
@@ -4038,6 +4038,21 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
     }
 
     @Override
+    public Authorizable createRemoteDataAuthorizable(String remoteGroupPortId) {
+        final DataAuthorizable authorizable;
+
+        final RemoteGroupPort remoteGroupPort = getRootGroup().findRemoteGroupPort(remoteGroupPortId);
+        if (remoteGroupPort == null) {
+            throw new ResourceNotFoundException("The component that generated this event is no longer part of the data flow.");
+        } else {
+            // authorizable for remote group ports should be the remote process group
+            authorizable = new DataAuthorizable(remoteGroupPort.getRemoteProcessGroup());
+        }
+
+        return authorizable;
+    }
+
+    @Override
     public List<Action> getFlowChanges(final int firstActionId, final int maxActions) {
         final History history = auditService.getActions(firstActionId, maxActions);
         return new ArrayList<>(history.getActions());

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingContext.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingContext.java
index ef84432..8f8b231 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingContext.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingContext.java
@@ -16,11 +16,6 @@
  */
 package org.apache.nifi.controller.reporting;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.nifi.attribute.expression.language.PreparedQuery;
 import org.apache.nifi.attribute.expression.language.Query;
 import org.apache.nifi.attribute.expression.language.StandardPropertyValue;
@@ -43,6 +38,11 @@ import org.apache.nifi.reporting.ReportingContext;
 import org.apache.nifi.reporting.ReportingTask;
 import org.apache.nifi.reporting.Severity;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 public class StandardReportingContext implements ReportingContext, ControllerServiceLookup {
 
     private final FlowController flowController;
@@ -95,7 +95,7 @@ public class StandardReportingContext implements ReportingContext, ControllerSer
     @Override
     public Bulletin createBulletin(final String componentId, final String category, final Severity severity, final String message) {
         final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId());
-        final Connectable connectable = rootGroup.findConnectable(componentId);
+        final Connectable connectable = rootGroup.findLocalConnectable(componentId);
         if (connectable == null) {
             throw new IllegalStateException("Cannot create Component-Level Bulletin because no component can be found with ID " + componentId);
         }

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/repository/StandardProcessSession.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/repository/StandardProcessSession.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/repository/StandardProcessSession.java
index 80c917c..f7dfd73 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/repository/StandardProcessSession.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/repository/StandardProcessSession.java
@@ -16,31 +16,6 @@
  */
 package org.apache.nifi.controller.repository;
 
-import java.io.ByteArrayInputStream;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
 import org.apache.commons.io.IOUtils;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.Connection;
@@ -79,6 +54,31 @@ import org.apache.nifi.stream.io.StreamUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
 /**
  * <p>
  * Provides a ProcessSession that ensures all accesses, changes and transfers
@@ -164,10 +164,10 @@ public final class StandardProcessSession implements ProcessSession, ProvenanceE
                 componentType = "Output Port";
                 break;
             case REMOTE_INPUT_PORT:
-                componentType = "Remote Input Port";
+                componentType = ProvenanceEventRecord.REMOTE_INPUT_PORT_TYPE;
                 break;
             case REMOTE_OUTPUT_PORT:
-                componentType = "Remote Output Port";
+                componentType = ProvenanceEventRecord.REMOTE_OUTPUT_PORT_TYPE;
                 break;
             case FUNNEL:
                 componentType = "Funnel";

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
index 2c9af28..49cbd94 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
@@ -1482,11 +1482,11 @@ public final class StandardProcessGroup implements ProcessGroup {
     }
 
     @Override
-    public Connectable findConnectable(final String identifier) {
-        return findConnectable(identifier, this);
+    public Connectable findLocalConnectable(final String identifier) {
+        return findLocalConnectable(identifier, this);
     }
 
-    private static Connectable findConnectable(final String identifier, final ProcessGroup group) {
+    private static Connectable findLocalConnectable(final String identifier, final ProcessGroup group) {
         final ProcessorNode procNode = group.getProcessor(identifier);
         if (procNode != null) {
             return procNode;
@@ -1507,6 +1507,21 @@ public final class StandardProcessGroup implements ProcessGroup {
             return funnel;
         }
 
+        for (final ProcessGroup childGroup : group.getProcessGroups()) {
+            final Connectable childGroupConnectable = findLocalConnectable(identifier, childGroup);
+            if (childGroupConnectable != null) {
+                return childGroupConnectable;
+            }
+        }
+
+        return null;
+    }
+
+    public RemoteGroupPort findRemoteGroupPort(final String identifier) {
+        return findRemoteGroupPort(identifier, this);
+    }
+
+    private static RemoteGroupPort findRemoteGroupPort(final String identifier, final ProcessGroup group) {
         for (final RemoteProcessGroup remoteGroup : group.getRemoteProcessGroups()) {
             final RemoteGroupPort remoteInPort = remoteGroup.getInputPort(identifier);
             if (remoteInPort != null) {
@@ -1520,9 +1535,9 @@ public final class StandardProcessGroup implements ProcessGroup {
         }
 
         for (final ProcessGroup childGroup : group.getProcessGroups()) {
-            final Connectable childGroupConnectable = findConnectable(identifier, childGroup);
-            if (childGroupConnectable != null) {
-                return childGroupConnectable;
+            final RemoteGroupPort childGroupRemoteGroupPort = findRemoteGroupPort(identifier, childGroup);
+            if (childGroupRemoteGroupPort != null) {
+                return childGroupRemoteGroupPort;
             }
         }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java
index 47faca5..838c53c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java
@@ -33,6 +33,7 @@ import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.groups.ProcessGroupCounts;
 import org.apache.nifi.groups.RemoteProcessGroup;
+import org.apache.nifi.remote.RemoteGroupPort;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -508,7 +509,12 @@ public class MockProcessGroup implements ProcessGroup {
     }
 
     @Override
-    public Connectable findConnectable(final String identifier) {
+    public Connectable findLocalConnectable(final String identifier) {
+        return null;
+    }
+
+    @Override
+    public RemoteGroupPort findRemoteGroupPort(String identifier) {
         return null;
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 a24edd9..b1d0844 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
@@ -116,24 +116,6 @@ public interface AuthorizableLookup {
     Authorizable getRemoteProcessGroup(String id);
 
     /**
-     * Get the authorizable RemoteProcessGroup input port.
-     *
-     * @param remoteProcessGroupId remote process group id
-     * @param id input port id
-     * @return authorizable
-     */
-    Authorizable getRemoteProcessGroupInputPort(String remoteProcessGroupId, String id);
-
-    /**
-     * Get the authorizable RemoteProcessGroup output port.
-     *
-     * @param remoteProcessGroupId remote process group id
-     * @param id output port id
-     * @return authorizable
-     */
-    Authorizable getRemoteProcessGroupOutputPort(String remoteProcessGroupId, String id);
-
-    /**
      * Get the authorizable Label.
      *
      * @param id label id
@@ -203,12 +185,12 @@ public interface AuthorizableLookup {
     TemplateAuthorizable getTemplate(String id);
 
     /**
-     * Get the authorizable connectable.
+     * Get the authorizable connectable. Note this does not include RemoteGroupPorts.
      *
      * @param id connectable id
      * @return authorizable
      */
-    Authorizable getConnectable(String id);
+    Authorizable getLocalConnectable(String id);
 
     /**
      * Get the snippet of authorizable's.
@@ -225,13 +207,6 @@ 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/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConnectionAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConnectionAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConnectionAuthorizable.java
index 76a8833..4fe2015 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConnectionAuthorizable.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConnectionAuthorizable.java
@@ -39,6 +39,13 @@ public interface ConnectionAuthorizable {
     Connectable getSource();
 
     /**
+     * Returns the data authorizable for the source of the connection.
+     *
+     * @return source data authorizable
+     */
+    Authorizable getSourceData();
+
+    /**
      * Returns the destination.
      *
      * @return destination
@@ -46,6 +53,13 @@ public interface ConnectionAuthorizable {
     Connectable getDestination();
 
     /**
+     * Returns the data authorizable for the destination of the connection.
+     *
+     * @return destination data authorizable
+     */
+    Authorizable getDestinationData();
+
+    /**
      * Returns the parent process group.
      *
      * @return parent

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 f74931d..18af600 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
@@ -38,7 +38,6 @@ import org.apache.nifi.controller.Template;
 import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.controller.service.ControllerServiceReference;
 import org.apache.nifi.groups.ProcessGroup;
-import org.apache.nifi.groups.RemoteProcessGroup;
 import org.apache.nifi.remote.PortAuthorizationResult;
 import org.apache.nifi.remote.RootGroupPort;
 import org.apache.nifi.web.ResourceNotFoundException;
@@ -240,18 +239,6 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public Authorizable getRemoteProcessGroupInputPort(final String remoteProcessGroupId, final String id) {
-        final RemoteProcessGroup remoteProcessGroup = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupId);
-        return remoteProcessGroup.getInputPort(id);
-    }
-
-    @Override
-    public Authorizable getRemoteProcessGroupOutputPort(final String remoteProcessGroupId, final String id) {
-        final RemoteProcessGroup remoteProcessGroup = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupId);
-        return remoteProcessGroup.getOutputPort(id);
-    }
-
-    @Override
     public Authorizable getLabel(final String id) {
         return labelDAO.getLabel(id);
     }
@@ -414,11 +401,6 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public Authorizable getData(final String id) {
-        return controllerFacade.getDataAuthorizable(id);
-    }
-
-    @Override
     public Authorizable getPolicies() {
         return POLICIES_AUTHORIZABLE;
     }
@@ -525,9 +507,6 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
             case Template:
                 authorizable = getTemplate(componentId).getAuthorizable();
                 break;
-            case Data:
-                authorizable = controllerFacade.getDataAuthorizable(componentId);
-                break;
         }
 
         if (authorizable == null) {
@@ -681,9 +660,15 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public Authorizable getConnectable(String id) {
+    public Authorizable getLocalConnectable(String id) {
         final ProcessGroup group = processGroupDAO.getProcessGroup(controllerFacade.getRootGroupId());
-        return group.findConnectable(id);
+        final Connectable connectable = group.findLocalConnectable(id);
+
+        if (connectable == null) {
+            throw new ResourceNotFoundException("Unable to find component with id " + id);
+        }
+
+        return connectable;
     }
 
     @Override
@@ -889,11 +874,21 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
         }
 
         @Override
+        public Authorizable getSourceData() {
+            return new DataAuthorizable(connection.getSourceAuthorizable());
+        }
+
+        @Override
         public Connectable getDestination() {
             return connection.getDestination();
         }
 
         @Override
+        public Authorizable getDestinationData() {
+            return new DataAuthorizable(connection.getDestinationAuthorizable());
+        }
+
+        @Override
         public ProcessGroup getParentGroup() {
             return connection.getProcessGroup();
         }

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.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/ConnectionResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java
index fb25211..cf6aada 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java
@@ -29,6 +29,7 @@ import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.connectable.Connectable;
+import org.apache.nifi.connectable.ConnectableType;
 import org.apache.nifi.web.NiFiServiceFacade;
 import org.apache.nifi.web.Revision;
 import org.apache.nifi.web.api.dto.ConnectionDTO;
@@ -203,8 +204,14 @@ public class ConnectionResource extends ApplicationResource {
                     + "requested resource (%s).", requestConnection.getId(), id));
         }
 
-        if (requestConnection.getDestination() != null && requestConnection.getDestination().getId() == null) {
-            throw new IllegalArgumentException("When specifying a destination component, the destination id is required.");
+        if (requestConnection.getDestination() != null) {
+            if (requestConnection.getDestination().getId() == null) {
+                throw new IllegalArgumentException("When specifying a destination component, the destination id is required.");
+            }
+
+            if (requestConnection.getDestination().getType() == null) {
+                throw new IllegalArgumentException("When specifying a destination component, the type of the destination is required.");
+            }
         }
 
         if (isReplicateRequest()) {
@@ -224,9 +231,23 @@ public class ConnectionResource extends ApplicationResource {
                     // if a destination has been specified and is different
                     final Connectable currentDestination = connAuth.getDestination();
                     if (requestConnection.getDestination() != null && !currentDestination.getIdentifier().equals(requestConnection.getDestination().getId())) {
-                        // verify access of the new destination (current destination was already authorized as part of the connection check)
-                        final Authorizable newDestinationAuthorizable = lookup.getConnectable(requestConnection.getDestination().getId());
-                        newDestinationAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                        try {
+                            final ConnectableType destinationConnectableType = ConnectableType.valueOf(requestConnection.getDestination().getType());
+
+                            // explicitly handle RPGs differently as the connectable id can be ambiguous if self referencing
+                            final Authorizable newDestinationAuthorizable;
+                            if (ConnectableType.REMOTE_INPUT_PORT.equals(destinationConnectableType)) {
+                                newDestinationAuthorizable = lookup.getRemoteProcessGroup(requestConnection.getDestination().getGroupId());
+                            } else {
+                                newDestinationAuthorizable = lookup.getLocalConnectable(requestConnection.getDestination().getId());
+                            }
+
+                            // verify access of the new destination (current destination was already authorized as part of the connection check)
+                            newDestinationAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                        } catch (final IllegalArgumentException e) {
+                            throw new IllegalArgumentException(String.format("Unrecognized destination type %s. Excepted values are [%s]",
+                                    requestConnection.getDestination().getType(), StringUtils.join(ConnectableType.values(), ", ")));
+                        }
 
                         // verify access of the parent group (this is the same check that is performed when creating the connection)
                         connAuth.getParentGroup().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 fbf4c55..ab232e8 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
@@ -331,7 +331,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                 requestConnectionEntity,
                 lookup -> {
                     final ConnectionAuthorizable connAuth = lookup.getConnection(id);
-                    final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+                    final Authorizable dataAuthorizable = connAuth.getSourceData();
                     dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
                 },
                 () -> serviceFacade.verifyListQueue(id),
@@ -400,7 +400,7 @@ public class FlowFileQueueResource extends ApplicationResource {
         // authorize access
         serviceFacade.authorizeAccess(lookup -> {
             final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
-            final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+            final Authorizable dataAuthorizable = connAuth.getSourceData();
             dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
         });
 
@@ -465,7 +465,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                 new ListingEntity(connectionId, listingRequestId),
                 lookup -> {
                     final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
-                    final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+                    final Authorizable dataAuthorizable = connAuth.getSourceData();
                     dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
                 },
                 null,
@@ -554,7 +554,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                 requestConnectionEntity,
                 lookup -> {
                     final ConnectionAuthorizable connAuth = lookup.getConnection(id);
-                    final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+                    final Authorizable dataAuthorizable = connAuth.getSourceData();
                     dataAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                 },
                 null,
@@ -623,7 +623,7 @@ public class FlowFileQueueResource extends ApplicationResource {
         // authorize access
         serviceFacade.authorizeAccess(lookup -> {
             final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
-            final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+            final Authorizable dataAuthorizable = connAuth.getSourceData();
             dataAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
         });
 
@@ -688,7 +688,7 @@ public class FlowFileQueueResource extends ApplicationResource {
                 new DropEntity(connectionId, dropRequestId),
                 lookup -> {
                     final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
-                    final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
+                    final Authorizable dataAuthorizable = connAuth.getSourceData();
                     dataAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                 },
                 null,

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.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/FlowResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
index 3119863..1b9bc99 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
@@ -651,7 +651,7 @@ public class FlowResource extends ApplicationResource {
 
                     // ensure access to every component being scheduled
                     requestComponentsToSchedule.keySet().forEach(componentId -> {
-                        final Authorizable connectable = lookup.getConnectable(componentId);
+                        final Authorizable connectable = lookup.getLocalConnectable(componentId);
                         connectable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                     });
                 },

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.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/ProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
index 8b9366f..5c8da85 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
@@ -36,6 +36,7 @@ import org.apache.nifi.authorization.TemplateAuthorizable;
 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.connectable.ConnectableType;
 import org.apache.nifi.web.NiFiServiceFacade;
 import org.apache.nifi.web.ResourceNotFoundException;
 import org.apache.nifi.web.Revision;
@@ -1523,10 +1524,34 @@ public class ProcessGroupResource extends ApplicationResource {
             throw new IllegalArgumentException("The source of the connection must be specified.");
         }
 
+        if (requestConnection.getSource().getType() == null) {
+            throw new IllegalArgumentException("The type of the source of the connection must be specified.");
+        }
+
+        final ConnectableType sourceConnectableType;
+        try {
+            sourceConnectableType = ConnectableType.valueOf(requestConnection.getSource().getType());
+        } catch (final IllegalArgumentException e) {
+            throw new IllegalArgumentException(String.format("Unrecognized source type %s. Expected values are [%s]",
+                    requestConnection.getSource().getType(), StringUtils.join(ConnectableType.values(), ", ")));
+        }
+
         if (requestConnection.getDestination() == null || requestConnection.getDestination().getId() == null) {
             throw new IllegalArgumentException("The destination of the connection must be specified.");
         }
 
+        if (requestConnection.getDestination().getType() == null) {
+            throw new IllegalArgumentException("The type of the destination of the connection must be specified.");
+        }
+
+        final ConnectableType destinationConnectableType;
+        try {
+            destinationConnectableType = ConnectableType.valueOf(requestConnection.getDestination().getType());
+        } catch (final IllegalArgumentException e) {
+            throw new IllegalArgumentException(String.format("Unrecognized destination type %s. Expected values are [%s]",
+                    requestConnection.getDestination().getType(), StringUtils.join(ConnectableType.values(), ", ")));
+        }
+
         if (isReplicateRequest()) {
             return replicate(HttpMethod.POST, requestConnectionEntity);
         }
@@ -1539,15 +1564,29 @@ public class ProcessGroupResource extends ApplicationResource {
                     final Authorizable processGroup = lookup.getProcessGroup(groupId).getAuthorizable();
                     processGroup.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
 
+                    // explicitly handle RPGs differently as the connectable id can be ambiguous if self referencing
+                    final Authorizable source;
+                    if (ConnectableType.REMOTE_OUTPUT_PORT.equals(sourceConnectableType)) {
+                        source = lookup.getRemoteProcessGroup(requestConnection.getSource().getGroupId());
+                    } else {
+                        source = lookup.getLocalConnectable(requestConnection.getSource().getId());
+                    }
+
                     // ensure write access to the source
-                    final Authorizable source = lookup.getConnectable(requestConnection.getSource().getId());
                     if (source == null) {
                         throw new ResourceNotFoundException("Cannot find source component with ID [" + requestConnection.getSource().getId() + "]");
                     }
                     source.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
 
+                    // explicitly handle RPGs differently as the connectable id can be ambiguous if self referencing
+                    final Authorizable destination;
+                    if (ConnectableType.REMOTE_INPUT_PORT.equals(destinationConnectableType)) {
+                        destination = lookup.getRemoteProcessGroup(requestConnection.getDestination().getGroupId());
+                    } else {
+                        destination = lookup.getLocalConnectable(requestConnection.getDestination().getId());
+                    }
+
                     // ensure write access to the destination
-                    final Authorizable destination = lookup.getConnectable(requestConnection.getDestination().getId());
                     if (destination == null) {
                         throw new ResourceNotFoundException("Cannot find destination component with ID [" + requestConnection.getDestination().getId() + "]");
                     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.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/RemoteProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java
index 04f6d19..5380d51 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java
@@ -291,8 +291,8 @@ public class RemoteProcessGroupResource extends ApplicationResource {
                 requestRemoteProcessGroupPortEntity,
                 requestRevision,
                 lookup -> {
-                    final Authorizable remoteProcessGroupInputPort = lookup.getRemoteProcessGroupInputPort(id, portId);
-                    remoteProcessGroupInputPort.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                    final Authorizable remoteProcessGroup = lookup.getRemoteProcessGroup(id);
+                    remoteProcessGroup.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                 },
                 () -> serviceFacade.verifyUpdateRemoteProcessGroupInputPort(id, requestRemoteProcessGroupPort),
                 (revision, remoteProcessGroupPortEntity) -> {
@@ -393,8 +393,8 @@ public class RemoteProcessGroupResource extends ApplicationResource {
                 requestRemoteProcessGroupPortEntity,
                 requestRevision,
                 lookup -> {
-                    final Authorizable remoteProcessGroupOutputPort = lookup.getRemoteProcessGroupOutputPort(id, portId);
-                    remoteProcessGroupOutputPort.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                    final Authorizable remoteProcessGroup = lookup.getRemoteProcessGroup(id);
+                    remoteProcessGroup.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                 },
                 () -> serviceFacade.verifyUpdateRemoteProcessGroupOutputPort(id, requestRemoteProcessGroupPort),
                 (revision, remoteProcessGroupPortEntity) -> {

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 30fcbd7..d526288 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
@@ -79,6 +79,7 @@ import org.apache.nifi.provenance.search.SearchTerm;
 import org.apache.nifi.provenance.search.SearchTerms;
 import org.apache.nifi.provenance.search.SearchableField;
 import org.apache.nifi.registry.VariableRegistry;
+import org.apache.nifi.remote.RemoteGroupPort;
 import org.apache.nifi.remote.RootGroupPort;
 import org.apache.nifi.reporting.ReportingTask;
 import org.apache.nifi.scheduling.ExecutionNode;
@@ -1172,7 +1173,12 @@ public class ControllerFacade implements Authorizable {
             }
 
             // authorize the event
-            final Authorizable dataAuthorizable = flowController.createDataAuthorizable(event.getComponentId());
+            final Authorizable dataAuthorizable;
+            if (event.isRemotePortType()) {
+                dataAuthorizable = flowController.createRemoteDataAuthorizable(event.getComponentId());
+            } else {
+                dataAuthorizable = flowController.createLocalDataAuthorizable(event.getComponentId());
+            }
             dataAuthorizable.authorize(authorizer, RequestAction.READ, user, attributes);
 
             // get the filename and fall back to the identifier (should never happen)
@@ -1215,7 +1221,7 @@ public class ControllerFacade implements Authorizable {
             }
 
             // authorize the replay
-            authorizeReplay(originalEvent.getComponentId(), originalEvent.getAttributes(), originalEvent.getSourceQueueIdentifier());
+            authorizeReplay(originalEvent);
 
             // replay the flow file
             final ProvenanceEventRecord event = flowController.replayFlowFile(originalEvent, user);
@@ -1230,18 +1236,23 @@ public class ControllerFacade implements Authorizable {
     /**
      * Authorizes access to replay a specified provenance event.
      *
-     * @param componentId component id
-     * @param eventAttributes event attributes
-     * @param connectionId connection id
+     * @param event event
      */
-    private AuthorizationResult checkAuthorizationForReplay(final String componentId, final Map<String, String> eventAttributes, final String connectionId) {
+    private AuthorizationResult checkAuthorizationForReplay(final ProvenanceEventRecord event) {
         // if the connection id isn't specified, then the replay wouldn't be available anyways and we have nothing to authorize against so deny it`
-        if (connectionId == null) {
+        if (event.getSourceQueueIdentifier() == null) {
             return AuthorizationResult.denied();
         }
 
         final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final Authorizable dataAuthorizable = flowController.createDataAuthorizable(componentId);
+        final Authorizable dataAuthorizable;
+        if (event.isRemotePortType()) {
+            dataAuthorizable = flowController.createRemoteDataAuthorizable(event.getComponentId());
+        } else {
+            dataAuthorizable = flowController.createLocalDataAuthorizable(event.getComponentId());
+        }
+
+        final Map<String, String> eventAttributes = event.getAttributes();
 
         // ensure we can read the data
         final AuthorizationResult result = dataAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, eventAttributes);
@@ -1256,20 +1267,24 @@ public class ControllerFacade implements Authorizable {
     /**
      * Authorizes access to replay a specified provenance event.
      *
-     * @param componentId component id
-     * @param eventAttributes event attributes
-     * @param connectionId connection id
+     * @param event event
      */
-    private void authorizeReplay(final String componentId, final Map<String, String> eventAttributes, final String connectionId) {
+    private void authorizeReplay(final ProvenanceEventRecord event) {
         // if the connection id isn't specified, then the replay wouldn't be available anyways and we have nothing to authorize against so deny it`
-        if (connectionId == null) {
+        if (event.getSourceQueueIdentifier() == null) {
             throw new AccessDeniedException("The connection id is unknown.");
         }
 
         final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final Authorizable dataAuthorizable = flowController.createDataAuthorizable(componentId);
+        final Authorizable dataAuthorizable;
+        if (event.isRemotePortType()) {
+            dataAuthorizable = flowController.createRemoteDataAuthorizable(event.getComponentId());
+        } else {
+            dataAuthorizable = flowController.createLocalDataAuthorizable(event.getComponentId());
+        }
 
         // ensure we can read and write the data
+        final Map<String, String> eventAttributes = event.getAttributes();
         dataAuthorizable.authorize(authorizer, RequestAction.READ, user, eventAttributes);
         dataAuthorizable.authorize(authorizer, RequestAction.WRITE, user, eventAttributes);
     }
@@ -1289,7 +1304,12 @@ public class ControllerFacade implements Authorizable {
 
             // get the flowfile attributes and authorize the event
             final Map<String, String> attributes = event.getAttributes();
-            final Authorizable dataAuthorizable = flowController.createDataAuthorizable(event.getComponentId());
+            final Authorizable dataAuthorizable;
+            if (event.isRemotePortType()) {
+                dataAuthorizable = flowController.createRemoteDataAuthorizable(event.getComponentId());
+            } else {
+                dataAuthorizable = flowController.createLocalDataAuthorizable(event.getComponentId());
+            }
             dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser(), attributes);
 
             // convert the event
@@ -1300,16 +1320,6 @@ public class ControllerFacade implements Authorizable {
     }
 
     /**
-     * Gets an authorizable for proveance events for a given component id.
-     *
-     * @param componentId component id
-     * @return authorizable
-     */
-    public Authorizable getDataAuthorizable(final String componentId) {
-        return flowController.createDataAuthorizable(componentId);
-    }
-
-    /**
      * Creates a ProvenanceEventDTO for the specified ProvenanceEventRecord.
      *
      * @param event event
@@ -1394,7 +1404,7 @@ public class ControllerFacade implements Authorizable {
         }
 
         // determine if authorized for event replay
-        final AuthorizationResult replayAuthorized = checkAuthorizationForReplay(event.getComponentId(), event.getAttributes(), event.getSourceQueueIdentifier());
+        final AuthorizationResult replayAuthorized = checkAuthorizationForReplay(event);
 
         // replay
         dto.setReplayAvailable(contentAvailability.isReplayable() && Result.Approved.equals(replayAuthorized.getResult()));
@@ -1432,13 +1442,20 @@ public class ControllerFacade implements Authorizable {
     private void setComponentDetails(final ProvenanceEventDTO dto) {
         final ProcessGroup root = flowController.getGroup(flowController.getRootGroupId());
 
-        final Connectable connectable = root.findConnectable(dto.getComponentId());
+        final Connectable connectable = root.findLocalConnectable(dto.getComponentId());
         if (connectable != null) {
             dto.setGroupId(connectable.getProcessGroup().getIdentifier());
             dto.setComponentName(connectable.getName());
             return;
         }
 
+        final RemoteGroupPort remoteGroupPort = root.findRemoteGroupPort(dto.getComponentId());
+        if (remoteGroupPort != null) {
+            dto.setGroupId(remoteGroupPort.getProcessGroupIdentifier());
+            dto.setComponentName(remoteGroupPort.getName());
+            return;
+        }
+
         final Connection connection = root.findConnection(dto.getComponentId());
         if (connection != null) {
             dto.setGroupId(connection.getProcessGroup().getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 7fc09da..4f3d944 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
@@ -19,6 +19,7 @@ package org.apache.nifi.web.dao.impl;
 import org.apache.nifi.authorization.Authorizer;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
+import org.apache.nifi.authorization.resource.DataAuthorizable;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.connectable.Connectable;
@@ -134,7 +135,7 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO
 
             // get the attributes and ensure appropriate access
             final Map<String, String> attributes = flowFile.getAttributes();
-            final Authorizable dataAuthorizable = flowController.createDataAuthorizable(connection.getSource().getIdentifier());
+            final Authorizable dataAuthorizable = new DataAuthorizable(connection.getSourceAuthorizable());
             dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser(), attributes);
 
             return flowFile;
@@ -397,14 +398,29 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO
         }
 
         final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId());
-        final Connectable sourceConnectable = rootGroup.findConnectable(sourceDto.getId());
-        if (sourceConnectable == null) {
-            throw new IllegalArgumentException("The specified source for the connection does not exist");
+
+        if (ConnectableType.REMOTE_OUTPUT_PORT.name().equals(sourceDto.getType())) {
+            final Connectable sourceConnectable = rootGroup.findRemoteGroupPort(sourceDto.getId());
+            if (sourceConnectable == null) {
+                throw new IllegalArgumentException("The specified source for the connection does not exist");
+            }
+        } else {
+            final Connectable sourceConnectable = rootGroup.findLocalConnectable(sourceDto.getId());
+            if (sourceConnectable == null) {
+                throw new IllegalArgumentException("The specified source for the connection does not exist");
+            }
         }
 
-        final Connectable destinationConnectable = rootGroup.findConnectable(destinationDto.getId());
-        if (destinationConnectable == null) {
-            throw new IllegalArgumentException("The specified destination for the connection does not exist");
+        if (ConnectableType.REMOTE_INPUT_PORT.name().equals(destinationDto.getType())) {
+            final Connectable destinationConnectable = rootGroup.findRemoteGroupPort(destinationDto.getId());
+            if (destinationConnectable == null) {
+                throw new IllegalArgumentException("The specified destination for the connection does not exist");
+            }
+        } else {
+            final Connectable destinationConnectable = rootGroup.findLocalConnectable(destinationDto.getId());
+            if (destinationConnectable == null) {
+                throw new IllegalArgumentException("The specified destination for the connection does not exist");
+            }
         }
     }
 
@@ -625,7 +641,7 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO
 
             // get the attributes and ensure appropriate access
             final Map<String, String> attributes = flowFile.getAttributes();
-            final Authorizable dataAuthorizable = flowController.createDataAuthorizable(connection.getSource().getIdentifier());
+            final Authorizable dataAuthorizable = new DataAuthorizable(connection.getSourceAuthorizable());
             dataAuthorizable.authorize(authorizer, RequestAction.READ, user, attributes);
 
             // get the filename and fall back to the identifier (should never happen)

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.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/StandardProcessGroupDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
index 8f52896..9af57b6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
@@ -80,7 +80,7 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
 
         final Set<Connectable> connectables = new HashSet<>(componentIds.size());
         for (final String componentId : componentIds) {
-            final Connectable connectable = group.findConnectable(componentId);
+            final Connectable connectable = group.findLocalConnectable(componentId);
             if (connectable == null) {
                 throw new ResourceNotFoundException("Unable to find component with id " + componentId);
             }
@@ -103,7 +103,7 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
         final ProcessGroup group = locateProcessGroup(flowController, groupId);
 
         for (final String componentId : componentIds) {
-            final Connectable connectable = group.findConnectable(componentId);
+            final Connectable connectable = group.findLocalConnectable(componentId);
             if (ScheduledState.RUNNING.equals(state)) {
                 if (ConnectableType.PROCESSOR.equals(connectable.getConnectableType())) {
                     connectable.getProcessGroup().startProcessor((ProcessorNode) connectable);

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js
index 7c671ab..cc01408 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js
@@ -116,6 +116,8 @@ nf.ConnectionDetails = (function () {
                 $('#read-only-connection-source-label').text('From output');
                 $('#read-only-connection-source').text(source.name);
                 $('#read-only-connection-source-group-name').text(remoteProcessGroup.name);
+
+                deferred.resolve();
             }).fail(function (xhr, status, error) {
                 if (xhr.status === 403) {
                     // populate source processor details

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
index c002e37..46c1578 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
@@ -614,7 +614,8 @@ nf.ng.ProvenanceTable = function (provenanceLineageCtrl) {
             }
 
             // conditionally support going to the component
-            if (isInShell && nf.Common.isDefinedAndNotNull(dataContext.groupId)) {
+            var isRemotePort = dataContext.componentType === 'Remote Input Port' || dataContext.componentType === 'Remote Output Port';
+            if (isInShell && nf.Common.isDefinedAndNotNull(dataContext.groupId) && isRemotePort === false) {
                 markup += '&nbsp;<div class="pointer go-to fa fa-long-arrow-right" title="Go To"></div>';
             }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 c20ce6e..03cc3b7 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
@@ -16,51 +16,6 @@
  */
 package org.apache.nifi.provenance;
 
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexNotFoundException;
@@ -119,6 +74,51 @@ import org.apache.nifi.web.ResourceNotFoundException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
 public class PersistentProvenanceRepository implements ProvenanceRepository {
 
     public static final String EVENT_CATEGORY = "Provenance Repository";
@@ -447,7 +447,11 @@ public class PersistentProvenanceRepository implements ProvenanceRepository {
 
         final Authorizable eventAuthorizable;
         try {
-            eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
+            if (event.isRemotePortType()) {
+                eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId());
+            } else {
+                eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId());
+            }
         } catch (final ResourceNotFoundException rnfe) {
             return false;
         }
@@ -461,7 +465,12 @@ public class PersistentProvenanceRepository implements ProvenanceRepository {
             return;
         }
 
-        final Authorizable eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
+        final Authorizable eventAuthorizable;
+        if (event.isRemotePortType()) {
+            eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId());
+        } else {
+            eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId());
+        }
         eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/b917e9be/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 6c04ecb..f889e8b 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
@@ -256,7 +256,11 @@ public class VolatileProvenanceRepository implements ProvenanceRepository {
 
         final Authorizable eventAuthorizable;
         try {
-            eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
+            if (event.isRemotePortType()) {
+                eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId());
+            } else {
+                eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId());
+            }
         } catch (final ResourceNotFoundException rnfe) {
             return false;
         }
@@ -270,7 +274,12 @@ public class VolatileProvenanceRepository implements ProvenanceRepository {
             return;
         }
 
-        final Authorizable eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
+        final Authorizable eventAuthorizable;
+        if (event.isRemotePortType()) {
+            eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId());
+        } else {
+            eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId());
+        }
         eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
     }