From 3f753b393f4a9d333dc5f77f89fa6b78fd01bbce Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Mon, 5 Dec 2016 11:15:29 -0500 Subject: [PATCH 1/9] NIFI-3133: - Ensuring that Remote Group Ports are always authorized according to their Remote Process Group. --- .../apache/nifi/connectable/Connection.java | 12 ++-- .../nifi/connectable/StandardConnection.java | 62 ++++++++++++++----- .../nifi/controller/FlowController.java | 7 ++- .../authorization/ConnectionAuthorizable.java | 14 +++++ .../StandardAuthorizableLookup.java | 20 +++++- .../nifi/web/api/ConnectionResource.java | 31 ++++++++-- .../nifi/web/api/FlowFileQueueResource.java | 12 ++-- .../nifi/web/api/ProcessGroupResource.java | 43 ++++++++++++- 8 files changed, 167 insertions(+), 34 deletions(-) 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 1d240b53c15c..f0d2e916ec07 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.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 getRelationships(); FlowFileQueue getFlowFileQueue(); @@ -59,6 +61,8 @@ public interface Connection extends Authorizable { Connectable getSource(); + Authorizable getSourceAuthorizable(); + void setRelationships(Collection newRelationships); void setDestination(final Connectable newDestination); 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 6d2228128cd8..3d5efedb1509 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.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 @@ -137,6 +139,36 @@ public String getName() { }; } + @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 resourceContext) { if (user == null) { @@ -144,13 +176,13 @@ public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestActi } // 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 void authorize(Authorizer authorizer, RequestAction action, NiFiUser user 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 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 0f22f51231e9..c460caaffa42 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 @@ -4034,7 +4034,12 @@ public Authorizable createDataAuthorizable(final String componentId) { authorizable = new DataAuthorizable(connection.getSource()); } } else { - authorizable = new DataAuthorizable(connectable); + // authorizable for remote group ports should be the remote process group + if (connectable instanceof RemoteGroupPort) { + authorizable = new DataAuthorizable(((RemoteGroupPort) connectable).getRemoteProcessGroup()); + } else { + authorizable = new DataAuthorizable(connectable); + } } } 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 76a88331fe6d..4fe2015e0a7a 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 @@ -38,6 +38,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. * @@ -45,6 +52,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. * 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 f74931df20f8..93ca32d829d9 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 @@ -40,6 +40,7 @@ import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.RemoteProcessGroup; import org.apache.nifi.remote.PortAuthorizationResult; +import org.apache.nifi.remote.RemoteGroupPort; import org.apache.nifi.remote.RootGroupPort; import org.apache.nifi.web.ResourceNotFoundException; import org.apache.nifi.web.api.dto.FlowSnippetDTO; @@ -683,7 +684,14 @@ public Set getEncapsulatedControllerServices( @Override public Authorizable getConnectable(String id) { final ProcessGroup group = processGroupDAO.getProcessGroup(controllerFacade.getRootGroupId()); - return group.findConnectable(id); + final Connectable connectable = group.findConnectable(id); + + // remote group ports are authorized according to their RPG + if (connectable instanceof RemoteGroupPort) { + return ((RemoteGroupPort) connectable).getRemoteProcessGroup(); + } else { + return connectable; + } } @Override @@ -888,11 +896,21 @@ public Connectable getSource() { return connection.getSource(); } + @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(); 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 fb25211a3ab1..a2afda070c2a 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.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 Response updateConnection( + "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 Response updateConnection( // 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.getConnectable(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()); 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 fbf4c55deaa8..ab232e836b2d 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 Response createFlowFileListing( 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 Response getListingRequest( // 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 Response deleteListingRequest( 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 Response createDropRequest( 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 Response getDropRequest( // 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 Response removeDropRequest( 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, 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 5809a066117e..d1b1513c3d9b 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.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.remote.util.SiteToSiteRestApiClient; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.ResourceNotFoundException; @@ -1505,10 +1506,34 @@ public Response createConnection( 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); } @@ -1521,15 +1546,29 @@ public Response createConnection( 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.getConnectable(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.getConnectable(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() + "]"); } From 6101877680dca51e9143ad20c09f77061faed9bd Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Mon, 5 Dec 2016 12:54:42 -0500 Subject: [PATCH 2/9] NIFI-3133: - Using getSourceAuthorizable() when accessing flow files and content. --- .../org/apache/nifi/web/dao/impl/StandardConnectionDAO.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 7fc09da061b5..a7d326a7fac5 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 @@ 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 FlowFileRecord getFlowFile(String id, String flowFileUuid) { // get the attributes and ensure appropriate access final Map 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; @@ -625,7 +626,7 @@ public DownloadableContent getContent(String id, String flowFileUuid, String req // get the attributes and ensure appropriate access final Map 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) From 5650eb6a8b7ec33c0c65cce577c3bb2cf2707934 Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Mon, 5 Dec 2016 16:47:37 -0500 Subject: [PATCH 3/9] NIFI-3133: - Decouple local and remote connectable's to avoid ambiguity with self referencing RPGs. --- .../provenance/ProvenanceEventRecord.java | 11 ++ .../ProvenanceAuthorizableFactory.java | 11 +- .../org/apache/nifi/groups/ProcessGroup.java | 12 +- .../nifi/controller/FlowController.java | 26 +++-- .../reporting/StandardReportingContext.java | 12 +- .../repository/StandardProcessSession.java | 54 ++++----- .../nifi/groups/StandardProcessGroup.java | 27 ++++- .../service/mock/MockProcessGroup.java | 8 +- .../authorization/AuthorizableLookup.java | 4 +- .../StandardAuthorizableLookup.java | 17 +-- .../nifi/web/api/ConnectionResource.java | 2 +- .../org/apache/nifi/web/api/FlowResource.java | 2 +- .../nifi/web/api/ProcessGroupResource.java | 4 +- .../nifi/web/controller/ControllerFacade.java | 65 +++++++---- .../web/dao/impl/StandardConnectionDAO.java | 22 +++- .../web/dao/impl/StandardProcessGroupDAO.java | 4 +- .../PersistentProvenanceRepository.java | 103 ++++++++++-------- .../VolatileProvenanceRepository.java | 13 ++- 18 files changed, 252 insertions(+), 145 deletions(-) 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 eaa34648c760..7ba1622b7b63 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 @@ */ 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 @@ -100,6 +103,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 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 96990414ec2c..0bbb190c80c3 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); } 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 be0bcd3876b7..122e45422399 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.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 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 c460caaffa42..59ea8fda02d0 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 @@ -4010,7 +4010,7 @@ public List getProvenanceEvents(final long firstEventId, } @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, @@ -4022,7 +4022,7 @@ public Authorizable createDataAuthorizable(final String componentId) { 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); @@ -4034,18 +4034,28 @@ public Authorizable createDataAuthorizable(final String componentId) { authorizable = new DataAuthorizable(connection.getSource()); } } else { - // authorizable for remote group ports should be the remote process group - if (connectable instanceof RemoteGroupPort) { - authorizable = new DataAuthorizable(((RemoteGroupPort) connectable).getRemoteProcessGroup()); - } else { - authorizable = new DataAuthorizable(connectable); - } + authorizable = new DataAuthorizable(connectable); } } return authorizable; } + @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 getFlowChanges(final int firstActionId, final int maxActions) { final History history = auditService.getActions(firstActionId, maxActions); 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 ef84432748ce..8f8b2314be96 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.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 Bulletin createBulletin(final String category, final Severity severity, f @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); } 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 80c917cebec3..f7dfd7330f6a 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.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; + /** *

* Provides a ProcessSession that ensures all accesses, changes and transfers @@ -164,10 +164,10 @@ public StandardProcessSession(final ProcessContext context) { 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"; 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 2c9af288f366..49cbd941760b 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 @@ private List findAllProcessors(final ProcessGroup start) { } @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 @@ private static Connectable findConnectable(final String identifier, final Proces 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 @@ private static Connectable findConnectable(final String identifier, final Proces } 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; } } 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 47faca5b0cd5..838c53cbe190 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.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 void remove(final Snippet snippet) { } @Override - public Connectable findConnectable(final String identifier) { + public Connectable findLocalConnectable(final String identifier) { + return null; + } + + @Override + public RemoteGroupPort findRemoteGroupPort(String identifier) { return null; } 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 a24edd99a572..1416cc611a64 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 @@ -203,12 +203,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. 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 93ca32d829d9..38bbf2de65df 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 @@ -40,7 +40,6 @@ import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.RemoteProcessGroup; import org.apache.nifi.remote.PortAuthorizationResult; -import org.apache.nifi.remote.RemoteGroupPort; import org.apache.nifi.remote.RootGroupPort; import org.apache.nifi.web.ResourceNotFoundException; import org.apache.nifi.web.api.dto.FlowSnippetDTO; @@ -416,7 +415,7 @@ public Authorizable getTenant() { @Override public Authorizable getData(final String id) { - return controllerFacade.getDataAuthorizable(id); + return controllerFacade.getLocalDataAuthorizable(id); } @Override @@ -526,9 +525,6 @@ private Authorizable getAccessPolicyByResource(final ResourceType resourceType, case Template: authorizable = getTemplate(componentId).getAuthorizable(); break; - case Data: - authorizable = controllerFacade.getDataAuthorizable(componentId); - break; } if (authorizable == null) { @@ -682,16 +678,9 @@ public Set getEncapsulatedControllerServices( } @Override - public Authorizable getConnectable(String id) { + public Authorizable getLocalConnectable(String id) { final ProcessGroup group = processGroupDAO.getProcessGroup(controllerFacade.getRootGroupId()); - final Connectable connectable = group.findConnectable(id); - - // remote group ports are authorized according to their RPG - if (connectable instanceof RemoteGroupPort) { - return ((RemoteGroupPort) connectable).getRemoteProcessGroup(); - } else { - return connectable; - } + return group.findLocalConnectable(id); } @Override 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 a2afda070c2a..cf6aada37eaa 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 @@ -239,7 +239,7 @@ public Response updateConnection( if (ConnectableType.REMOTE_INPUT_PORT.equals(destinationConnectableType)) { newDestinationAuthorizable = lookup.getRemoteProcessGroup(requestConnection.getDestination().getGroupId()); } else { - newDestinationAuthorizable = lookup.getConnectable(requestConnection.getDestination().getId()); + newDestinationAuthorizable = lookup.getLocalConnectable(requestConnection.getDestination().getId()); } // verify access of the new destination (current destination was already authorized as part of the connection check) 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 3119863d30ef..1b9bc99c3d16 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 Response scheduleComponents( // 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()); }); }, 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 d1b1513c3d9b..df9b476bed77 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 @@ -1551,7 +1551,7 @@ public Response createConnection( if (ConnectableType.REMOTE_OUTPUT_PORT.equals(sourceConnectableType)) { source = lookup.getRemoteProcessGroup(requestConnection.getSource().getGroupId()); } else { - source = lookup.getConnectable(requestConnection.getSource().getId()); + source = lookup.getLocalConnectable(requestConnection.getSource().getId()); } // ensure write access to the source @@ -1565,7 +1565,7 @@ public Response createConnection( if (ConnectableType.REMOTE_INPUT_PORT.equals(destinationConnectableType)) { destination = lookup.getRemoteProcessGroup(requestConnection.getDestination().getGroupId()); } else { - destination = lookup.getConnectable(requestConnection.getDestination().getId()); + destination = lookup.getLocalConnectable(requestConnection.getDestination().getId()); } // ensure write access to the destination 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 2db2bbe835f5..08c29604f8d9 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.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 DownloadableContent getContent(final Long eventId, final String uri, fina } // 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 ProvenanceEventDTO submitReplay(final Long eventId) { } // 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 ProvenanceEventDTO submitReplay(final Long eventId) { /** * 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 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 eventAttributes = event.getAttributes(); // ensure we can read the data final AuthorizationResult result = dataAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, eventAttributes); @@ -1256,20 +1267,24 @@ private AuthorizationResult checkAuthorizationForReplay(final String componentId /** * 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 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 eventAttributes = event.getAttributes(); dataAuthorizable.authorize(authorizer, RequestAction.READ, user, eventAttributes); dataAuthorizable.authorize(authorizer, RequestAction.WRITE, user, eventAttributes); } @@ -1289,7 +1304,12 @@ public ProvenanceEventDTO getProvenanceEvent(final Long eventId) { // get the flowfile attributes and authorize the event final Map 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 @@ -1305,8 +1325,8 @@ public ProvenanceEventDTO getProvenanceEvent(final Long eventId) { * @param componentId component id * @return authorizable */ - public Authorizable getDataAuthorizable(final String componentId) { - return flowController.createDataAuthorizable(componentId); + public Authorizable getLocalDataAuthorizable(final String componentId) { + return flowController.createLocalDataAuthorizable(componentId); } /** @@ -1394,7 +1414,7 @@ public int compare(AttributeDTO a1, AttributeDTO a2) { } // 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 +1452,20 @@ public int compare(AttributeDTO a1, AttributeDTO a2) { 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 (connectable != 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()); 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 a7d326a7fac5..0e141aa4dab2 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 @@ -398,14 +398,28 @@ public void verifyCreate(String groupId, ConnectionDTO connectionDTO) { } final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId()); - final Connectable sourceConnectable = rootGroup.findConnectable(sourceDto.getId()); + Connectable sourceConnectable = rootGroup.findLocalConnectable(sourceDto.getId()); if (sourceConnectable == null) { - throw new IllegalArgumentException("The specified source for the connection does not exist"); + sourceConnectable = rootGroup.findRemoteGroupPort(sourceDto.getId()); + + // ensure the source connectable was found + if (sourceConnectable == null) { + throw new IllegalArgumentException("The specified source for the connection does not exist"); + } else if (!ConnectableType.REMOTE_OUTPUT_PORT.name().equals(sourceDto.getType())) { + throw new IllegalArgumentException("The specified source for the connection is not a valid type"); + } } - final Connectable destinationConnectable = rootGroup.findConnectable(destinationDto.getId()); + Connectable destinationConnectable = rootGroup.findLocalConnectable(destinationDto.getId()); if (destinationConnectable == null) { - throw new IllegalArgumentException("The specified destination for the connection does not exist"); + destinationConnectable = rootGroup.findRemoteGroupPort(destinationDto.getId()); + + // ensure the destination connectable was found + if (destinationConnectable == null) { + throw new IllegalArgumentException("The specified destination for the connection does not exist"); + } else if (!ConnectableType.REMOTE_INPUT_PORT.name().equals(destinationDto.getType())) { + throw new IllegalArgumentException("The specified destination for the connection is not a valid type"); + } } } 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 8f528965c643..9af57b618251 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 void verifyScheduleComponents(final String groupId, final ScheduledState final Set 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 void scheduleComponents(final String groupId, final ScheduledState state, 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); 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 c20ce6ecc47b..03cc3b73052f 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.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 boolean isAuthorized(final ProvenanceEventRecord event, final NiFiUser us 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 @@ protected void authorize(final ProvenanceEventRecord event, final NiFiUser user) 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()); } 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 6c04ecba5272..f889e8b351c9 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 boolean isAuthorized(final ProvenanceEventRecord event, final NiFiUser us 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 @@ protected void authorize(final ProvenanceEventRecord event, final NiFiUser user) 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()); } From 0e2735ca4987b6de7f48ec05a23decc6f24e0bff Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Mon, 5 Dec 2016 17:13:43 -0500 Subject: [PATCH 4/9] NIFI-3133: - Addressing comments from the PR. --- .../nifi/authorization/AuthorizableLookup.java | 7 ------- .../authorization/StandardAuthorizableLookup.java | 5 ----- .../apache/nifi/web/controller/ControllerFacade.java | 12 +----------- 3 files changed, 1 insertion(+), 23 deletions(-) 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 1416cc611a64..f084961595b5 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 @@ -224,13 +224,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. * 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 38bbf2de65df..1c7ecbca799a 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 @@ -413,11 +413,6 @@ public Authorizable getTenant() { return TENANT_AUTHORIZABLE; } - @Override - public Authorizable getData(final String id) { - return controllerFacade.getLocalDataAuthorizable(id); - } - @Override public Authorizable getPolicies() { return POLICIES_AUTHORIZABLE; 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 08c29604f8d9..55a0235ba2f9 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 @@ -1319,16 +1319,6 @@ public ProvenanceEventDTO getProvenanceEvent(final Long eventId) { } } - /** - * Gets an authorizable for proveance events for a given component id. - * - * @param componentId component id - * @return authorizable - */ - public Authorizable getLocalDataAuthorizable(final String componentId) { - return flowController.createLocalDataAuthorizable(componentId); - } - /** * Creates a ProvenanceEventDTO for the specified ProvenanceEventRecord. * @@ -1460,7 +1450,7 @@ private void setComponentDetails(final ProvenanceEventDTO dto) { } final RemoteGroupPort remoteGroupPort = root.findRemoteGroupPort(dto.getComponentId()); - if (connectable != null) { + if (remoteGroupPort != null) { dto.setGroupId(remoteGroupPort.getProcessGroupIdentifier()); dto.setComponentName(remoteGroupPort.getName()); return; From 06b071467da37d3f2e5b648f679a8f055bf08172 Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Mon, 5 Dec 2016 17:37:23 -0500 Subject: [PATCH 5/9] NIFI-3133: - Fixed check verifying source/destination when creating a connection. --- .../web/dao/impl/StandardConnectionDAO.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) 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 0e141aa4dab2..4f3d9442841c 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 @@ -398,27 +398,28 @@ public void verifyCreate(String groupId, ConnectionDTO connectionDTO) { } final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId()); - Connectable sourceConnectable = rootGroup.findLocalConnectable(sourceDto.getId()); - if (sourceConnectable == null) { - sourceConnectable = rootGroup.findRemoteGroupPort(sourceDto.getId()); - // ensure the source connectable was found + 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"); - } else if (!ConnectableType.REMOTE_OUTPUT_PORT.name().equals(sourceDto.getType())) { - throw new IllegalArgumentException("The specified source for the connection is not a valid type"); } } - Connectable destinationConnectable = rootGroup.findLocalConnectable(destinationDto.getId()); - if (destinationConnectable == null) { - destinationConnectable = rootGroup.findRemoteGroupPort(destinationDto.getId()); - - // ensure the destination connectable was found + 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"); - } else if (!ConnectableType.REMOTE_INPUT_PORT.name().equals(destinationDto.getType())) { - throw new IllegalArgumentException("The specified destination for the connection is not a valid type"); } } } From 1f89b829e01c708a15bdf0a384218694fcc50a80 Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Mon, 5 Dec 2016 18:07:02 -0500 Subject: [PATCH 6/9] NIFI-3133: - Only showing the go to link when the source component is not a remote port. --- .../src/main/webapp/js/nf/provenance/nf-provenance-table.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 c002e37dc72b..46c15781c357 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 += ' 

'; } From a73bc97fe1d36f26b64cfd30287b1a52d36ca3bb Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Mon, 5 Dec 2016 18:27:30 -0500 Subject: [PATCH 7/9] NIFI-3133: - Removing unnecessary checking of remote group port authorization since it's handled by the parent RPG. --- .../nifi/authorization/AuthorizableLookup.java | 18 ------------------ .../StandardAuthorizableLookup.java | 13 ------------- .../web/api/RemoteProcessGroupResource.java | 8 ++++---- 3 files changed, 4 insertions(+), 35 deletions(-) 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 f084961595b5..b1d0844e5025 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 @@ -115,24 +115,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. * 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 1c7ecbca799a..a973b9cecab9 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.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; @@ -239,18 +238,6 @@ public Authorizable getRemoteProcessGroup(final String id) { return remoteProcessGroupDAO.getRemoteProcessGroup(id); } - @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); 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 04f6d19b6aa5..5380d51cd3d5 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 Response updateRemoteProcessGroupInputPort( 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 Response updateRemoteProcessGroupOutputPort( 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) -> { From 01fd7aec6cc119b2fad5bab9ee89eb7017adb7da Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Mon, 5 Dec 2016 18:39:49 -0500 Subject: [PATCH 8/9] NIFI-3133: - Fixing issue showing the connection details dialog when the source component is a RPG. --- .../nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js | 2 ++ 1 file changed, 2 insertions(+) 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 7c671ab63404..cc01408b2049 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 From 0c1f26df680fe3f688ae6775f735d6de029d9e4b Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Mon, 5 Dec 2016 18:50:45 -0500 Subject: [PATCH 9/9] NIFI-3133: - Ensuring the local connectable was found. --- .../nifi/authorization/StandardAuthorizableLookup.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 a973b9cecab9..18af600ecabf 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 @@ -662,7 +662,13 @@ public Set getEncapsulatedControllerServices( @Override public Authorizable getLocalConnectable(String id) { final ProcessGroup group = processGroupDAO.getProcessGroup(controllerFacade.getRootGroupId()); - return group.findLocalConnectable(id); + final Connectable connectable = group.findLocalConnectable(id); + + if (connectable == null) { + throw new ResourceNotFoundException("Unable to find component with id " + id); + } + + return connectable; } @Override