mirror of https://github.com/apache/nifi.git
NIFI-12696 Added Component Type to Rule Violations for Authorization
RuleViolations (these objects only reside in memory only) now contain the type of the component that is responsible for the violation. This is used in StandardNiFiServiceFacade to fix and improve the authorization logic. This closes #8318 Signed-off-by: David Handermann <exceptionfactory@apache.org>
This commit is contained in:
parent
5f534dcc42
commit
49e599385d
|
@ -18,6 +18,7 @@ package org.apache.nifi.validation;
|
|||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.nifi.flow.ComponentType;
|
||||
import org.apache.nifi.flowanalysis.EnforcementPolicy;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
|
@ -32,6 +33,7 @@ public class RuleViolation {
|
|||
private final String scope;
|
||||
private final String subjectId;
|
||||
private final String subjectDisplayName;
|
||||
private final ComponentType subjectComponentType;
|
||||
private final String groupId;
|
||||
private final String ruleId;
|
||||
private final String issueId;
|
||||
|
@ -45,6 +47,7 @@ public class RuleViolation {
|
|||
String scope,
|
||||
String subjectId,
|
||||
String subjectDisplayName,
|
||||
ComponentType subjectComponentType,
|
||||
String groupId,
|
||||
String ruleId,
|
||||
String issueId,
|
||||
|
@ -55,6 +58,7 @@ public class RuleViolation {
|
|||
this.scope = scope;
|
||||
this.subjectId = subjectId;
|
||||
this.subjectDisplayName = subjectDisplayName;
|
||||
this.subjectComponentType = subjectComponentType;
|
||||
this.groupId = groupId;
|
||||
this.ruleId = ruleId;
|
||||
this.issueId = issueId;
|
||||
|
@ -92,6 +96,13 @@ public class RuleViolation {
|
|||
return subjectDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type of the subject that violated the rule
|
||||
*/
|
||||
public ComponentType getSubjectComponentType() {
|
||||
return subjectComponentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return group id - if this violation is a result of a component analysis, then the id of the group of the component.
|
||||
* If this violation is a result of a group analysis, then the id of that group itself.
|
||||
|
@ -146,6 +157,7 @@ public class RuleViolation {
|
|||
.add("scope='" + scope + "'")
|
||||
.add("subjectId='" + subjectId + "'")
|
||||
.add("subjectDisplayName='" + subjectDisplayName + "'")
|
||||
.add("subjectComponentType='" + subjectComponentType + "'")
|
||||
.add("groupId='" + groupId + "'")
|
||||
.add("issueId='" + issueId + "'")
|
||||
.add("ruleId='" + ruleId + "'")
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.nifi.controller.flowanalysis.FlowAnalysisUtil;
|
|||
import org.apache.nifi.controller.flowanalysis.FlowAnalyzer;
|
||||
import org.apache.nifi.controller.service.ControllerServiceNode;
|
||||
import org.apache.nifi.controller.service.ControllerServiceProvider;
|
||||
import org.apache.nifi.flow.ComponentType;
|
||||
import org.apache.nifi.flow.VersionedComponent;
|
||||
import org.apache.nifi.flow.VersionedConnection;
|
||||
import org.apache.nifi.flow.VersionedControllerService;
|
||||
|
@ -108,6 +109,8 @@ public class StandardFlowAnalyzer implements FlowAnalyzer {
|
|||
long start = System.currentTimeMillis();
|
||||
|
||||
String componentId = component.getIdentifier();
|
||||
ComponentType componentType = component.getComponentType();
|
||||
|
||||
Set<FlowAnalysisRuleNode> flowAnalysisRules = flowAnalysisRuleProvider.getAllFlowAnalysisRules();
|
||||
|
||||
Set<RuleViolation> violations = flowAnalysisRules.stream()
|
||||
|
@ -126,6 +129,7 @@ public class StandardFlowAnalyzer implements FlowAnalyzer {
|
|||
componentId,
|
||||
componentId,
|
||||
getDisplayName(component),
|
||||
componentType,
|
||||
component.getGroupIdentifier(),
|
||||
ruleId,
|
||||
analysisResult.getIssueId(),
|
||||
|
@ -175,6 +179,7 @@ public class StandardFlowAnalyzer implements FlowAnalyzer {
|
|||
Map<VersionedComponent, Collection<RuleViolation>> componentToRuleViolations
|
||||
) {
|
||||
String groupId = processGroup.getIdentifier();
|
||||
ComponentType processGroupComponentType = processGroup.getComponentType();
|
||||
|
||||
flowAnalysisRules.stream()
|
||||
.filter(FlowAnalysisRuleNode::isEnabled)
|
||||
|
@ -199,6 +204,7 @@ public class StandardFlowAnalyzer implements FlowAnalyzer {
|
|||
component.getGroupIdentifier(),
|
||||
component.getIdentifier(),
|
||||
getDisplayName(component),
|
||||
component.getComponentType(),
|
||||
component.getGroupIdentifier(),
|
||||
ruleId,
|
||||
analysisResult.getIssueId(),
|
||||
|
@ -212,6 +218,7 @@ public class StandardFlowAnalyzer implements FlowAnalyzer {
|
|||
groupId,
|
||||
groupId,
|
||||
getDisplayName(processGroup),
|
||||
processGroupComponentType,
|
||||
groupId,
|
||||
ruleId,
|
||||
analysisResult.getIssueId(),
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.apache.nifi.admin.service.AuditService;
|
|||
import org.apache.nifi.attribute.expression.language.Query;
|
||||
import org.apache.nifi.authorization.AccessDeniedException;
|
||||
import org.apache.nifi.authorization.AccessPolicy;
|
||||
import org.apache.nifi.authorization.AuthorizableHolder;
|
||||
import org.apache.nifi.authorization.AuthorizableLookup;
|
||||
import org.apache.nifi.authorization.AuthorizationRequest;
|
||||
import org.apache.nifi.authorization.AuthorizationResult;
|
||||
|
@ -6486,10 +6485,16 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
ruleViolationDto.setViolationMessage(ruleViolation.getViolationMessage());
|
||||
|
||||
String subjectId = ruleViolation.getSubjectId();
|
||||
String groupId = ruleViolation.getGroupId();
|
||||
|
||||
ruleViolationDto.setSubjectId(subjectId);
|
||||
ruleViolationDto.setGroupId(ruleViolation.getGroupId());
|
||||
ruleViolationDto.setGroupId(groupId);
|
||||
ruleViolationDto.setSubjectDisplayName(ruleViolation.getSubjectDisplayName());
|
||||
ruleViolationDto.setSubjectPermissionDto(createPermissionDto(subjectId));
|
||||
ruleViolationDto.setSubjectPermissionDto(createPermissionDto(
|
||||
subjectId,
|
||||
ruleViolation.getSubjectComponentType(),
|
||||
groupId
|
||||
));
|
||||
|
||||
return ruleViolationDto;
|
||||
})
|
||||
|
@ -6501,21 +6506,33 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
return entity;
|
||||
}
|
||||
|
||||
private PermissionsDTO createPermissionDto(String id) {
|
||||
private PermissionsDTO createPermissionDto(
|
||||
final String id,
|
||||
final org.apache.nifi.flow.ComponentType subjectComponentType,
|
||||
final String groupId
|
||||
) {
|
||||
final InstantiatedVersionedComponent versionedComponent = new InstantiatedVersionedComponent() {
|
||||
@Override
|
||||
public String getInstanceIdentifier() {
|
||||
return id;
|
||||
}
|
||||
|
||||
Optional<AuthorizableHolder> authorizableHolder = findAuthorizableHolder(
|
||||
id,
|
||||
authorizableLookup::getProcessor,
|
||||
authorizableLookup::getControllerService,
|
||||
authorizableLookup::getConnection,
|
||||
authorizableLookup::getProcessGroup,
|
||||
authorizableLookup::getPublicInputPort,
|
||||
authorizableLookup::getPublicOutputPort
|
||||
);
|
||||
@Override
|
||||
public String getInstanceGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
};
|
||||
|
||||
Authorizable authorizable;
|
||||
try {
|
||||
authorizable = getAuthorizable(subjectComponentType.name(), versionedComponent);
|
||||
} catch (Exception e) {
|
||||
authorizable = null;
|
||||
}
|
||||
|
||||
final PermissionsDTO permissionDto;
|
||||
if (authorizableHolder.isPresent()) {
|
||||
permissionDto = dtoFactory.createPermissionsDto(authorizableHolder.get().getAuthorizable(), NiFiUserUtils.getNiFiUser());
|
||||
if (authorizable != null) {
|
||||
permissionDto = dtoFactory.createPermissionsDto(authorizable, NiFiUserUtils.getNiFiUser());
|
||||
} else {
|
||||
permissionDto = new PermissionsDTO();
|
||||
permissionDto.setCanRead(false);
|
||||
|
@ -6525,25 +6542,6 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
return permissionDto;
|
||||
}
|
||||
|
||||
private Optional<AuthorizableHolder> findAuthorizableHolder(
|
||||
final String id,
|
||||
final Function<String, AuthorizableHolder>... lookupMethods
|
||||
) {
|
||||
AuthorizableHolder authorizableHolder = null;
|
||||
for (Function<String, AuthorizableHolder> lookupMethod : lookupMethods) {
|
||||
try {
|
||||
authorizableHolder = lookupMethod.apply(id);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// We don't know beforehand what kind of component we are looking for. Ignore if one lookup fails.
|
||||
}
|
||||
if (authorizableHolder != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.ofNullable(authorizableHolder);
|
||||
}
|
||||
|
||||
/* reusable function declarations for converting ids to tenant entities */
|
||||
private Function<String, TenantEntity> mapUserGroupIdToTenantEntity(final boolean enforceGroupExistence) {
|
||||
return userGroupId -> {
|
||||
|
|
|
@ -926,6 +926,7 @@ public class StandardNiFiServiceFacadeTest {
|
|||
"scope" + ruleViolationCounter,
|
||||
"subjectId" + ruleViolationCounter,
|
||||
"subjectDisplayName" + ruleViolationCounter,
|
||||
null,
|
||||
groupId,
|
||||
"ruleId" + ruleViolationCounter,
|
||||
"issueId" + ruleViolationCounter,
|
||||
|
|
Loading…
Reference in New Issue