Skip to content

Commit

Permalink
NIFI-3785: Fixed user authorization errors. Removed unused imports.
Browse files Browse the repository at this point in the history
  • Loading branch information
Freedom9339 committed Dec 19, 2024
1 parent 353607b commit bedb313
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.authorization.AuthorizableLookup;
import org.apache.nifi.authorization.AuthorizeControllerServiceReference;
import org.apache.nifi.authorization.AuthorizeParameterReference;
import org.apache.nifi.authorization.Authorizer;
Expand Down Expand Up @@ -719,57 +720,45 @@ public Response getProcessGroupOptions(
final NiFiUser user = NiFiUserUtils.getNiFiUser();

final ComponentAuthorizable authorizableControllerService = lookup.getControllerService(controllerServiceId);
authorizableControllerService.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);
boolean authorized = authorizableControllerService.getAuthorizable().isAuthorized(authorizer, RequestAction.WRITE, user);

final ControllerServiceDTO controllerServiceDTO = serviceFacade.getControllerService(controllerServiceId, true).getComponent();

final ProcessGroupAuthorizable authorizableProcessGroupCurrent = lookup.getProcessGroup(controllerServiceDTO.getParentGroupId());
authorizableProcessGroupCurrent.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);

if (authorizableProcessGroupCurrent.getProcessGroup().getParent() != null) {
final ProcessGroupAuthorizable authorizableProcessGroupParent = lookup.getProcessGroup(authorizableProcessGroupCurrent.getProcessGroup().getParent().getIdentifier());
authorizableProcessGroupParent.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);
authorized = authorized && authorizableProcessGroupCurrent.getAuthorizable().isAuthorized(authorizer, RequestAction.WRITE, user);

if (authorized) {
if (authorizableProcessGroupCurrent.getProcessGroup().getParent() != null) {
final ProcessGroupAuthorizable authorizableProcessGroupParent = lookup.getProcessGroup(authorizableProcessGroupCurrent.getProcessGroup().getParent().getIdentifier());
if (authorizableProcessGroupParent.getAuthorizable().isAuthorized(authorizer, RequestAction.READ, user)
&& authorizableProcessGroupParent.getAuthorizable().isAuthorized(authorizer, RequestAction.WRITE, user)) {
options.add(generateProcessGroupOption(controllerServiceDTO, authorizableProcessGroupParent, lookup, user));
}
}

options.add(generateProcessGroupOption(controllerServiceDTO, authorizableProcessGroupParent));
authorizableProcessGroupCurrent.getProcessGroup().getProcessGroups().forEach(processGroup -> {
final ProcessGroupAuthorizable authorizableProcessGroup = lookup.getProcessGroup(processGroup.getIdentifier());
if (authorizableProcessGroup.getAuthorizable().isAuthorized(authorizer, RequestAction.READ, user)
&& authorizableProcessGroup.getAuthorizable().isAuthorized(authorizer, RequestAction.WRITE, user)) {
options.add(generateProcessGroupOption(controllerServiceDTO, authorizableProcessGroup, lookup, user));
}
});
}

authorizableProcessGroupCurrent.getProcessGroup().getProcessGroups().forEach(processGroup -> {
final ProcessGroupAuthorizable authorizableProcessGroup = lookup.getProcessGroup(processGroup.getIdentifier());
authorizableProcessGroup.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);
options.add(generateProcessGroupOption(controllerServiceDTO, authorizableProcessGroup));
});
});

return generateOkResponse(options).build();
}

private ProcessGroupOptionEntity generateProcessGroupOption(ControllerServiceDTO controllerServiceDTO, ProcessGroupAuthorizable processGroup) {
List<String> conflictingComponents = new ArrayList<>();
controllerServiceDTO.getReferencingComponents().forEach(e -> {
if (processGroup.getProcessGroup().findProcessor(e.getId()) == null
&& processGroup.getProcessGroup().findControllerService(e.getId(), true, false) == null) {
conflictingComponents.add("[" + e.getComponent().getName() + "]");
}
});

controllerServiceDTO.getProperties().forEach((key, value) -> {
try {
ControllerServiceEntity refControllerService = serviceFacade.getControllerService(value, false);
if (refControllerService != null) {
if (processGroup.getProcessGroup().findControllerService(value, false, true) == null) {
conflictingComponents.add("[" + refControllerService.getComponent().getName() + "]");
}
}
} catch (Exception ignored) { }
});
private ProcessGroupOptionEntity generateProcessGroupOption(ControllerServiceDTO controllerServiceDTO, ProcessGroupAuthorizable processGroup, AuthorizableLookup lookup, NiFiUser user) {
List<String> conflictingComponents = getConflictingComponents(controllerServiceDTO, processGroup, lookup, user);

ProcessGroupOptionEntity option = new ProcessGroupOptionEntity();
option.setText(processGroup.getProcessGroup().getName());
option.setValue(processGroup.getProcessGroup().getIdentifier());
option.setDisabled(false);

if (!conflictingComponents.isEmpty()) {
String errorMessage = "Could not move controller service because the following components would be out of scope: ";
String errorMessage = "Cannot move to this process group because the following components would be out of scope: ";
errorMessage += String.join(" ", conflictingComponents);
option.setDescription(errorMessage);
option.setDisabled(true);
Expand All @@ -778,6 +767,38 @@ private ProcessGroupOptionEntity generateProcessGroupOption(ControllerServiceDTO
return option;
}

private List<String> getConflictingComponents(ControllerServiceDTO controllerServiceDTO, ProcessGroupAuthorizable processGroup, AuthorizableLookup lookup, NiFiUser user) {
List<String> conflictingComponents = new ArrayList<>();
controllerServiceDTO.getReferencingComponents().forEach(referencingComponent -> {
if (processGroup.getProcessGroup().findProcessor(referencingComponent.getId()) == null
&& processGroup.getProcessGroup().findControllerService(referencingComponent.getId(), true, false) == null) {
final Authorizable componentAuthorizable = lookup.getControllerServiceReferencingComponent(controllerServiceDTO.getId(), referencingComponent.getId());
if (componentAuthorizable.isAuthorized(authorizer, RequestAction.READ, user)) {
conflictingComponents.add("[" + referencingComponent.getComponent().getName() + "]");
} else {
conflictingComponents.add("[Unauthorized Component]");
}
}
});

controllerServiceDTO.getProperties().forEach((key, value) -> {
try {
ControllerServiceEntity refControllerService = serviceFacade.getControllerService(value, false);
if (refControllerService != null) {
if (processGroup.getProcessGroup().findControllerService(value, false, true) == null) {
ComponentAuthorizable componentAuthorizable = lookup.getControllerService(value);
if (componentAuthorizable.getAuthorizable().isAuthorized(authorizer, RequestAction.READ, user)) {
conflictingComponents.add("[" + refControllerService.getComponent().getName() + "]");
} else {
conflictingComponents.add("[Unauthorized Component]");
}
}
}
} catch (Exception ignored) { }
});
return conflictingComponents;
}

/**
* Moves the specified Controller Service to parent/child process groups.
*
Expand Down Expand Up @@ -831,47 +852,32 @@ public Response moveControllerServices(
throw new IllegalArgumentException("ParentGroupId must be specified.");
}

final ControllerServiceDTO requestControllerServiceDTO = serviceFacade.getControllerService(id, true).getComponent();

final Revision requestRevision = getRevision(requestControllerServiceEntity, id);
return withWriteLock(
serviceFacade,
serviceFacade.getControllerService(id, true),
requestRevision,
lookup -> {
NiFiUser user = NiFiUserUtils.getNiFiUser();
// authorize the service
final ComponentAuthorizable authorizable = lookup.getControllerService(requestControllerServiceDTO.getId());
authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
final ComponentAuthorizable authorizableControllerService = lookup.getControllerService(id);

if (authorizableControllerService.getAuthorizable().isAuthorized(authorizer, RequestAction.WRITE, user)) {
throw new IllegalStateException("You do not have permission to perform this action.");
}

authorizableControllerService.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);
final ControllerServiceDTO requestControllerServiceDTO = serviceFacade.getControllerService(id, true).getComponent();

// authorize the current and new process groups
final ProcessGroupAuthorizable authorizableProcessGroupNew = lookup.getProcessGroup(requestControllerServiceEntity.getParentGroupId());
authorizableProcessGroupNew.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
authorizableProcessGroupNew.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);

final ProcessGroupAuthorizable authorizableProcessGroupOld = lookup.getProcessGroup(requestControllerServiceDTO.getParentGroupId());
authorizableProcessGroupOld.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
authorizableProcessGroupOld.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);

// Verify all referencing and referenced components are still within scope
List<String> conflictingComponents = new ArrayList<>();
requestControllerServiceDTO.getReferencingComponents().forEach(e -> {
if (authorizableProcessGroupNew.getProcessGroup().findProcessor(e.getId()) == null
&& authorizableProcessGroupNew.getProcessGroup().findControllerService(e.getId(), true, false) == null) {
conflictingComponents.add("[" + e.getComponent().getName() + "]");
}

final Authorizable referencingComponent = lookup.getControllerServiceReferencingComponent(requestControllerServiceDTO.getId(), e.getId());
OperationAuthorizable.authorizeOperation(referencingComponent, authorizer, NiFiUserUtils.getNiFiUser());
});

requestControllerServiceDTO.getProperties().forEach((key, value) -> {
try {
ControllerServiceEntity refControllerService = serviceFacade.getControllerService(value, false);
if (refControllerService != null) {
if (authorizableProcessGroupNew.getProcessGroup().findControllerService(value, false, true) == null) {
conflictingComponents.add("[" + refControllerService.getComponent().getName() + "]");
}
}
} catch (Exception ignored) { }
});
List<String> conflictingComponents = getConflictingComponents(requestControllerServiceDTO, authorizableProcessGroupNew, lookup, user);

if (!conflictingComponents.isEmpty()) {
String errorMessage = "Could not move controller service because the following components would be out of scope: ";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ export const selectCurrentParameterContext = createSelector(

export const selectCanvasPermissions = createSelector(selectFlowState, (state: FlowState) => state.flow.permissions);

export const selectProcessGroupFlow = createSelector(
selectFlowState,
(state: FlowState) => state.flow.processGroupFlow
);

export const selectBreadcrumbs = createSelector(
selectFlowState,
(state: FlowState) => state.flow.processGroupFlow.breadcrumb
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,52 +16,45 @@
*/

import { Component, Inject, Input } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import {
MAT_DIALOG_DATA,
MatDialogActions,
MatDialogClose,
MatDialogContent,
MatDialogTitle
} from '@angular/material/dialog';
import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';

import { MatInputModule } from '@angular/material/input';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatButtonModule } from '@angular/material/button';
import { AsyncPipe, NgTemplateOutlet } from '@angular/common';
import { MatTabsModule } from '@angular/material/tabs';
import { MatOptionModule } from '@angular/material/core';
import { MatSelectModule } from '@angular/material/select';
import { MatFormField } from '@angular/material/input';
import { MatButton } from '@angular/material/button';
import { MatOption } from '@angular/material/core';
import { MatLabel, MatSelect } from '@angular/material/select';
import { TextTip, NifiTooltipDirective, SelectOption } from '@nifi/shared';
import { Store } from '@ngrx/store';
import { CloseOnEscapeDialog } from '@nifi/shared';
import { NiFiState } from 'apps/nifi/src/app/state';
import { NgIf } from '@angular/common';
import {
ControllerServiceEntity,
ControllerServiceReferencingComponent,
ControllerServiceReferencingComponentEntity
} from 'apps/nifi/src/app/state/shared';
import { ControllerServiceApi } from 'apps/nifi/src/app/ui/common/controller-service/controller-service-api/controller-service-api.component';
import { ControllerServiceEntity, ControllerServiceReferencingComponent } from 'apps/nifi/src/app/state/shared';
import { ControllerServiceReferences } from 'apps/nifi/src/app/ui/common/controller-service/controller-service-references/controller-service-references.component';
import { NifiSpinnerDirective } from 'apps/nifi/src/app/ui/common/spinner/nifi-spinner.directive';
import { MoveControllerServiceDialogRequestSuccess } from '../../../state/controller-services';
import { moveControllerService } from '../../../state/controller-services/controller-services.actions';
import { BreadcrumbEntity } from '../../../state/shared';

@Component({
selector: 'move-controller-service',
standalone: true,
templateUrl: './move-controller-service.component.html',
imports: [
MatDialogContent,
ReactiveFormsModule,
MatDialogModule,
MatInputModule,
MatCheckboxModule,
MatButtonModule,
MatTabsModule,
MatOptionModule,
MatSelectModule,
ControllerServiceApi,
ControllerServiceReferences,
AsyncPipe,
NifiSpinnerDirective,
MatFormField,
MatSelect,
MatDialogTitle,
MatLabel,
NifiTooltipDirective,
NgTemplateOutlet,
MatOption,
ControllerServiceReferences,
MatDialogActions,
MatButton,
MatDialogClose,
NgIf
],
styleUrls: ['./move-controller-service.component.scss']
Expand Down

0 comments on commit bedb313

Please sign in to comment.