NIFI-4885:

- Updating the versioning endpoints to account for the granular access restrictions.

This closes #2573.

Signed-off-by: Bryan Bende <bbende@apache.org>
This commit is contained in:
Matt Gilman 2018-03-21 10:23:49 -04:00 committed by Bryan Bende
parent 478e34082d
commit 98cd9ad531
No known key found for this signature in database
GPG Key ID: A0DDA9ED50711C39
5 changed files with 63 additions and 42 deletions

View File

@ -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.
*

View File

@ -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.");

View File

@ -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<ConfigurableComponent> getRestrictedComponents(final VersionedProcessGroup group) {
final Set<ConfigurableComponent> restrictedComponents = new HashSet<>();
final Set<Tuple<String, BundleCoordinate>> 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<Tuple<String, BundleCoordinate>> componentTypes) {

View File

@ -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<ConfigurableComponent> restrictedComponents = FlowRegistryUtils.getRestrictedComponents(versionedFlowSnapshot.getFlowContents());
restrictedComponents.forEach(restrictedComponent -> {
final ComponentAuthorizable restrictedComponentAuthorizable = lookup.getConfigurableComponent(restrictedComponent);
authorizeRestrictions(authorizer, restrictedComponentAuthorizable);
});
}
},
() -> {

View File

@ -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<ConfigurableComponent> 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<ConfigurableComponent> 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