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 3f956569f5..363f0a537a 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 @@ -17,6 +17,7 @@ package org.apache.nifi.authorization; import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.components.ConfigurableComponent; import org.apache.nifi.components.RequiredPermission; import org.apache.nifi.web.api.dto.BundleDTO; import org.apache.nifi.web.api.dto.FlowSnippetDTO; @@ -41,6 +42,15 @@ public interface AuthorizableLookup { */ ComponentAuthorizable getConfigurableComponent(String type, BundleDTO bundle); + /** + * Get the authorizable for the given ConfigurableComponent. This will use a dummy instance of + * the component. + * + * @param configurableComponent the configurable component + * @return authorizable + */ + ComponentAuthorizable getConfigurableComponent(ConfigurableComponent configurableComponent); + /** * Get the authorizable Processor. * 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 42b3a55cc4..d70d5faa89 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 @@ -181,8 +181,13 @@ class StandardAuthorizableLookup implements AuthorizableLookup { @Override public ComponentAuthorizable getConfigurableComponent(final String type, final BundleDTO bundle) { + final ConfigurableComponent configurableComponent = controllerFacade.getTemporaryComponent(type, bundle); + return getConfigurableComponent(configurableComponent); + } + + @Override + public ComponentAuthorizable getConfigurableComponent(ConfigurableComponent configurableComponent) { try { - final ConfigurableComponent configurableComponent = controllerFacade.getTemporaryComponent(type, bundle); return new ConfigurableComponentAuthorizable(configurableComponent); } catch (final Exception e) { throw new AccessDeniedException("Unable to create component to verify if it references any Controller Services."); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/registry/flow/FlowRegistryUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/registry/flow/FlowRegistryUtils.java index b1da06ace7..1125d9cd54 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/registry/flow/FlowRegistryUtils.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/registry/flow/FlowRegistryUtils.java @@ -17,9 +17,6 @@ package org.apache.nifi.registry.flow; -import java.util.HashSet; -import java.util.Set; - import org.apache.nifi.annotation.behavior.Restricted; import org.apache.nifi.bundle.BundleCoordinate; import org.apache.nifi.components.ConfigurableComponent; @@ -28,9 +25,14 @@ import org.apache.nifi.util.Tuple; import org.apache.nifi.web.NiFiCoreException; import org.apache.nifi.web.api.dto.BundleDTO; +import java.util.HashSet; +import java.util.Set; + public class FlowRegistryUtils { - public static boolean containsRestrictedComponent(final VersionedProcessGroup group) { + public static Set getRestrictedComponents(final VersionedProcessGroup group) { + final Set restrictedComponents = new HashSet<>(); + final Set> componentTypes = new HashSet<>(); populateComponentTypes(group, componentTypes); @@ -42,11 +44,11 @@ public class FlowRegistryUtils { final boolean isRestricted = component.getClass().isAnnotationPresent(Restricted.class); if (isRestricted) { - return true; + restrictedComponents.add(component); } } - return false; + return restrictedComponents; } private static void populateComponentTypes(final VersionedProcessGroup group, final Set> componentTypes) { 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 ce266da69e..2cbcf56ad6 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 @@ -40,6 +40,7 @@ import org.apache.nifi.authorization.user.NiFiUserDetails; import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.bundle.BundleCoordinate; import org.apache.nifi.cluster.manager.NodeResponse; +import org.apache.nifi.components.ConfigurableComponent; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.controller.ScheduledState; import org.apache.nifi.controller.serialization.FlowEncodingVersion; @@ -1689,10 +1690,11 @@ public class ProcessGroupResource extends ApplicationResource { // for write access to the RestrictedComponents resource final VersionedFlowSnapshot versionedFlowSnapshot = requestProcessGroupEntity.getVersionedFlowSnapshot(); if (versionedFlowSnapshot != null) { - final boolean containsRestrictedComponent = FlowRegistryUtils.containsRestrictedComponent(versionedFlowSnapshot.getFlowContents()); - if (containsRestrictedComponent) { - lookup.getRestrictedComponents().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser()); - } + final Set restrictedComponents = FlowRegistryUtils.getRestrictedComponents(versionedFlowSnapshot.getFlowContents()); + restrictedComponents.forEach(restrictedComponent -> { + final ComponentAuthorizable restrictedComponentAuthorizable = lookup.getConfigurableComponent(restrictedComponent); + authorizeRestrictions(authorizer, restrictedComponentAuthorizable); + }); } }, () -> { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/VersionsResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/VersionsResource.java index 6286ce78a2..f1a005327a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/VersionsResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/VersionsResource.java @@ -17,31 +17,23 @@ package org.apache.nifi.web.api; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.HttpMethod; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; - +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.authorization.AccessDeniedException; import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.authorization.ComponentAuthorizable; import org.apache.nifi.authorization.ProcessGroupAuthorizable; import org.apache.nifi.authorization.RequestAction; 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.cluster.manager.NodeResponse; +import org.apache.nifi.components.ConfigurableComponent; import org.apache.nifi.controller.FlowController; import org.apache.nifi.controller.ScheduledState; import org.apache.nifi.controller.service.ControllerServiceState; @@ -85,6 +77,21 @@ import org.apache.nifi.web.util.LifecycleManagementException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -100,13 +107,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.stream.Collectors; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Authorization; - @Path("/versions") @Api(value = "/versions", description = "Endpoint for managing version control for a flow") public class VersionsResource extends ApplicationResource { @@ -1113,10 +1113,11 @@ public class VersionsResource extends ApplicationResource { authorizeProcessGroup(groupAuthorizable, authorizer, lookup, RequestAction.WRITE, true, false, true, true); final VersionedProcessGroup groupContents = flowSnapshot.getFlowContents(); - final boolean containsRestrictedComponents = FlowRegistryUtils.containsRestrictedComponent(groupContents); - if (containsRestrictedComponents) { - lookup.getRestrictedComponents().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser()); - } + final Set restrictedComponents = FlowRegistryUtils.getRestrictedComponents(groupContents); + restrictedComponents.forEach(restrictedComponent -> { + final ComponentAuthorizable restrictedComponentAuthorizable = lookup.getConfigurableComponent(restrictedComponent); + authorizeRestrictions(authorizer, restrictedComponentAuthorizable); + }); }, () -> { // Step 3: Verify that all components in the snapshot exist on all nodes @@ -1269,10 +1270,11 @@ public class VersionsResource extends ApplicationResource { authorizeProcessGroup(groupAuthorizable, authorizer, lookup, RequestAction.WRITE, true, false, true, true); final VersionedProcessGroup groupContents = flowSnapshot.getFlowContents(); - final boolean containsRestrictedComponents = FlowRegistryUtils.containsRestrictedComponent(groupContents); - if (containsRestrictedComponents) { - lookup.getRestrictedComponents().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser()); - } + final Set restrictedComponents = FlowRegistryUtils.getRestrictedComponents(groupContents); + restrictedComponents.forEach(restrictedComponent -> { + final ComponentAuthorizable restrictedComponentAuthorizable = lookup.getConfigurableComponent(restrictedComponent); + authorizeRestrictions(authorizer, restrictedComponentAuthorizable); + }); }, () -> { // Step 3: Verify that all components in the snapshot exist on all nodes