Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;

import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.flow.VersionedParameterContext;
import org.apache.nifi.registry.flow.FlowSnapshotContainer;
import org.apache.nifi.registry.flow.RegisteredFlowSnapshot;
import org.apache.nifi.web.NiFiServiceFacade;

import java.util.Map;
import java.util.Set;

/**
* Authorizes replacing the contents of a Process Group with a proposed flow snapshot along with resolved references
*/
public final class AuthorizeFlowUpdate {
/**
* Identifiers of inherited Controller Services and Parameter Providers from a proposed snapshot that could not be
* resolved against the local flow.
*
* @param controllerServices unresolved inherited Controller Service identifiers
* @param parameterProviders unresolved Parameter Provider identifiers
*/
public record UnresolvedReferences(Set<String> controllerServices, Set<String> parameterProviders) {
}

/**
* Resolves inherited references on the proposed snapshot and then authorizes the current user requesting flow updates
*
* @param groupId the id of the process group being updated
* @param flowSnapshot the proposed flow contents
* @param serviceFacade the service facade
* @param authorizer the authorizer
* @param lookup the authorizable lookup
* @param user the user to authorize
*/
public static void resolveAndAuthorizeFlowUpdate(
final String groupId,
final RegisteredFlowSnapshot flowSnapshot,
final NiFiServiceFacade serviceFacade,
final Authorizer authorizer,
final AuthorizableLookup lookup,
final NiFiUser user
) {
final FlowSnapshotContainer flowSnapshotContainer = new FlowSnapshotContainer(flowSnapshot);
final UnresolvedReferences unresolvedReferences = resolveReferences(groupId, flowSnapshotContainer, serviceFacade, user);
authorizeFlowUpdate(groupId, flowSnapshot, unresolvedReferences, serviceFacade, authorizer, lookup, user);
}

/**
* Discovers compatible bundles for the proposed snapshot and resolves the inherited Controller Services and the
* Parameter Providers that it references to components in the local flow
*
* @param groupId the id of the process group being updated
* @param flowSnapshotContainer the proposed flow snapshot along with the snapshots of any version controlled child groups
* @param serviceFacade the service facade
* @param user the user performing the update
* @return the references that could not be resolved against the local flow
*/
public static UnresolvedReferences resolveReferences(
final String groupId,
final FlowSnapshotContainer flowSnapshotContainer,
final NiFiServiceFacade serviceFacade,
final NiFiUser user
) {
final RegisteredFlowSnapshot flowSnapshot = flowSnapshotContainer.getFlowSnapshot();

// Discover compatible bundles since the flow snapshot can contain different versions
serviceFacade.discoverCompatibleBundles(flowSnapshot.getFlowContents());
serviceFacade.discoverCompatibleBundles(flowSnapshot.getParameterProviders());

// If there are any Controller Services referenced that are inherited from the parent group, resolve those to point to the appropriate Controller Service
final Set<String> unresolvedControllerServices = serviceFacade.resolveInheritedControllerServices(flowSnapshotContainer, groupId, user);

// If there are any Parameter Providers referenced by Parameter Contexts, resolve these to point to the appropriate Parameter Provider
final Set<String> unresolvedParameterProviders = serviceFacade.resolveParameterProviders(flowSnapshot, user);

return new UnresolvedReferences(unresolvedControllerServices, unresolvedParameterProviders);
}

/**
* Authorizes READ and WRITE permissions for the given user on the Process Group being updated
*
* @param groupId the id of the process group being updated
* @param flowSnapshot the proposed flow contents
* @param unresolvedReferences the references from the proposed snapshot that could not be resolved against the local flow
* @param serviceFacade the service facade
* @param authorizer the authorizer
* @param lookup the authorizable lookup
* @param user the user to authorize
*/
public static void authorizeFlowUpdate(
final String groupId,
final RegisteredFlowSnapshot flowSnapshot,
final UnresolvedReferences unresolvedReferences,
final NiFiServiceFacade serviceFacade,
final Authorizer authorizer,
final AuthorizableLookup lookup,
final NiFiUser user
) {
final ProcessGroupAuthorizable groupAuthorizable = lookup.getProcessGroup(groupId);
AuthorizeProcessGroup.authorizeProcessGroup(groupAuthorizable, authorizer, lookup, RequestAction.READ, true, false, true, false, true);
AuthorizeProcessGroup.authorizeProcessGroup(groupAuthorizable, authorizer, lookup, RequestAction.WRITE, true, false, true, false, false);

final Map<String, VersionedParameterContext> parameterContexts = flowSnapshot.getParameterContexts();
if (parameterContexts != null) {
for (final VersionedParameterContext parameterContext : parameterContexts.values()) {
AuthorizeParameterReference.authorizeParameterContextAddition(parameterContext, serviceFacade, authorizer, lookup, user);
}
}

AuthorizeParameterProviders.authorizeUnresolvedParameterProviders(unresolvedReferences.parameterProviders(), authorizer, lookup, user);
AuthorizeControllerServiceReference.authorizeUnresolvedControllerServiceReferences(groupId, unresolvedReferences.controllerServices(), authorizer, lookup, user);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;

import org.apache.nifi.authorization.resource.Authorizable;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserUtils;

import java.util.function.Consumer;

/**
* Authorizes a Process Group along with encapsulated and referenced Components
*/
public final class AuthorizeProcessGroup {
/**
* Authorizes the specified Process Group and referenced Components
*
* @param processGroupAuthorizable process group
* @param authorizer authorizer
* @param lookup lookup
* @param action action
* @param authorizeReferencedServices whether to authorize referenced services
* @param authorizeControllerServices whether to authorize controller services
* @param authorizeTransitiveServices whether to authorize transitive services
* @param authorizeParameterReferences whether to authorize parameter context that contained referenced parameter if applicable
* @param authorizeParameterContext whether to authorize the bound parameter context if applicable
*/
public static void authorizeProcessGroup(
final ProcessGroupAuthorizable processGroupAuthorizable,
final Authorizer authorizer,
final AuthorizableLookup lookup,
final RequestAction action,
final boolean authorizeReferencedServices,
final boolean authorizeControllerServices,
final boolean authorizeTransitiveServices,
final boolean authorizeParameterReferences,
final boolean authorizeParameterContext
) {
final NiFiUser user = NiFiUserUtils.getNiFiUser();
final Consumer<Authorizable> authorize = authorizable -> authorizable.authorize(authorizer, action, user);


authorize.accept(processGroupAuthorizable.getAuthorizable());


if (authorizeParameterContext) {
processGroupAuthorizable.getParameterContextAuthorizable().ifPresent(authorize);
}

processGroupAuthorizable.getEncapsulatedProcessors().forEach(processorAuthorizable -> {
authorize.accept(processorAuthorizable.getAuthorizable());
if (authorizeReferencedServices) {
AuthorizeControllerServiceReference.authorizeControllerServiceReferences(processorAuthorizable, authorizer, lookup, authorizeTransitiveServices);
}
if (authorizeParameterReferences) {
AuthorizeParameterReference.authorizeParameterReferences(processorAuthorizable, authorizer, processorAuthorizable.getParameterContext(), user);
}
});
processGroupAuthorizable.getEncapsulatedConnections().stream().map(AuthorizableHolder::getAuthorizable).forEach(authorize);
processGroupAuthorizable.getEncapsulatedInputPorts().forEach(authorize);
processGroupAuthorizable.getEncapsulatedOutputPorts().forEach(authorize);
processGroupAuthorizable.getEncapsulatedFunnels().forEach(authorize);
processGroupAuthorizable.getEncapsulatedLabels().forEach(authorize);
processGroupAuthorizable.getEncapsulatedProcessGroups().forEach(pga -> {
final Authorizable authorizable = pga.getAuthorizable();

authorize.accept(authorizable);

if (authorizeParameterContext) {
pga.getParameterContextAuthorizable().ifPresent(authorize);
}
});
processGroupAuthorizable.getEncapsulatedRemoteProcessGroups().forEach(authorize);

if (authorizeControllerServices) {
processGroupAuthorizable.getEncapsulatedControllerServices().forEach(controllerServiceAuthorizable -> {
authorize.accept(controllerServiceAuthorizable.getAuthorizable());
if (authorizeReferencedServices) {
AuthorizeControllerServiceReference.authorizeControllerServiceReferences(controllerServiceAuthorizable, authorizer, lookup, authorizeTransitiveServices);
}
if (authorizeParameterReferences) {
AuthorizeParameterReference.authorizeParameterReferences(controllerServiceAuthorizable, authorizer, controllerServiceAuthorizable.getParameterContext(), user);
}
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.apache.nifi.authorization.AuthorizeAccess;
import org.apache.nifi.authorization.AuthorizeControllerServiceReference;
import org.apache.nifi.authorization.AuthorizeParameterReference;
import org.apache.nifi.authorization.AuthorizeProcessGroup;
import org.apache.nifi.authorization.Authorizer;
import org.apache.nifi.authorization.ProcessGroupAuthorizable;
import org.apache.nifi.authorization.RequestAction;
Expand Down Expand Up @@ -430,69 +431,28 @@ protected Revision getRevision(final ComponentEntity entity, final String compon
* @param authorizeParameterReferences whether to authorize parameter context that contained referenced parameter if applicable
* @param authorizeParameterContext whether to authorize the bound parameter context if applicable
*/
protected void authorizeProcessGroup(final ProcessGroupAuthorizable processGroupAuthorizable, final Authorizer authorizer, final AuthorizableLookup lookup, final RequestAction action,
final boolean authorizeReferencedServices,
final boolean authorizeControllerServices, final boolean authorizeTransitiveServices,
final boolean authorizeParameterReferences, final boolean authorizeParameterContext) {

final NiFiUser user = NiFiUserUtils.getNiFiUser();
final Consumer<Authorizable> authorize = authorizable -> authorizable.authorize(authorizer, action, user);

// authorize the process group
authorize.accept(processGroupAuthorizable.getAuthorizable());

// authorize the parameter context for the specified process group
if (authorizeParameterContext) {
processGroupAuthorizable.getParameterContextAuthorizable().ifPresent(authorize);
}

// authorize the contents of the group - these methods return all encapsulated components (recursive)
processGroupAuthorizable.getEncapsulatedProcessors().forEach(processorAuthorizable -> {
// authorize the processor
authorize.accept(processorAuthorizable.getAuthorizable());

// authorize any referenced services if necessary
if (authorizeReferencedServices) {
AuthorizeControllerServiceReference.authorizeControllerServiceReferences(processorAuthorizable, authorizer, lookup, authorizeTransitiveServices);
}

// authorize any referenced parameters if necessary
if (authorizeParameterReferences) {
AuthorizeParameterReference.authorizeParameterReferences(processorAuthorizable, authorizer, processorAuthorizable.getParameterContext(), user);
}
});
processGroupAuthorizable.getEncapsulatedConnections().stream().map(connection -> connection.getAuthorizable()).forEach(authorize);
processGroupAuthorizable.getEncapsulatedInputPorts().forEach(authorize);
processGroupAuthorizable.getEncapsulatedOutputPorts().forEach(authorize);
processGroupAuthorizable.getEncapsulatedFunnels().forEach(authorize);
processGroupAuthorizable.getEncapsulatedLabels().forEach(authorize);
processGroupAuthorizable.getEncapsulatedProcessGroups().forEach(pga -> {
final Authorizable authorizable = pga.getAuthorizable();

authorize.accept(authorizable);

if (authorizeParameterContext) {
pga.getParameterContextAuthorizable().ifPresent(authorize);
}
});
processGroupAuthorizable.getEncapsulatedRemoteProcessGroups().forEach(authorize);

// authorize controller services if necessary
if (authorizeControllerServices) {
processGroupAuthorizable.getEncapsulatedControllerServices().forEach(controllerServiceAuthorizable -> {
// authorize the controller service
authorize.accept(controllerServiceAuthorizable.getAuthorizable());

// authorize any referenced services if necessary
if (authorizeReferencedServices) {
AuthorizeControllerServiceReference.authorizeControllerServiceReferences(controllerServiceAuthorizable, authorizer, lookup, authorizeTransitiveServices);
}

if (authorizeParameterReferences) {
AuthorizeParameterReference.authorizeParameterReferences(controllerServiceAuthorizable, authorizer, controllerServiceAuthorizable.getParameterContext(), user);
}
});
}
protected void authorizeProcessGroup(
final ProcessGroupAuthorizable processGroupAuthorizable,
final Authorizer authorizer,
final AuthorizableLookup lookup,
final RequestAction action,
final boolean authorizeReferencedServices,
final boolean authorizeControllerServices,
final boolean authorizeTransitiveServices,
final boolean authorizeParameterReferences,
final boolean authorizeParameterContext
) {
AuthorizeProcessGroup.authorizeProcessGroup(
processGroupAuthorizable,
authorizer,
lookup,
action,
authorizeReferencedServices,
authorizeControllerServices,
authorizeTransitiveServices,
authorizeParameterReferences,
authorizeParameterContext
);
}

/**
Expand Down
Loading
Loading