This is an automated email from the ASF dual-hosted git repository.
pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 08a558e151 NIFI-14765 Corrected Authorizable Lookup for Nested
Controller Objects
08a558e151 is described below
commit 08a558e151db0f5f64d77dac4511d078547b10ee
Author: exceptionfactory <[email protected]>
AuthorDate: Fri Jul 18 22:46:25 2025 -0500
NIFI-14765 Corrected Authorizable Lookup for Nested Controller Objects
- Added Resource Type resolution for Registry Client and Flow Analysis Rule
components nested under the Controller
Signed-off-by: Pierre Villard <[email protected]>
This closes #10110.
---
.../authorization/StandardAuthorizableLookup.java | 17 ++++++
.../StandardAuthorizableLookupTest.java | 69 ++++++++++++++++++----
2 files changed, 73 insertions(+), 13 deletions(-)
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
index a780e5f22b..ffa8933231 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
@@ -591,6 +591,23 @@ public class StandardAuthorizableLookup implements
AuthorizableLookup {
return new
OperationAuthorizable(getAccessPolicy(baseResourceType, resource));
}
+ case Controller:
+ // Handle Nested Resource Types such as Flow Analysis Rules
and Flow Registry Clients
+ final ResourceType nestedResourceType;
+ if
(resource.startsWith(ResourceType.RegistryClient.getValue())) {
+ nestedResourceType = ResourceType.RegistryClient;
+ } else if
(resource.startsWith(ResourceType.FlowAnalysisRule.getValue())) {
+ nestedResourceType = ResourceType.FlowAnalysisRule;
+ } else {
+ nestedResourceType = null;
+ }
+
+ if (nestedResourceType == null) {
+ return getAccessPolicy(resourceType, resource);
+ } else {
+ final String componentId =
StringUtils.substringAfter(resource,
nestedResourceType.getValue()).substring(1);
+ return getAccessPolicyByResource(nestedResourceType,
componentId);
+ }
case RestrictedComponents:
final String slashRequiredPermission =
StringUtils.substringAfter(resource, resourceType.getValue());
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/authorization/StandardAuthorizableLookupTest.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/authorization/StandardAuthorizableLookupTest.java
index 319b4aab6e..116f55c727 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/authorization/StandardAuthorizableLookupTest.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/authorization/StandardAuthorizableLookupTest.java
@@ -22,13 +22,18 @@ import
org.apache.nifi.authorization.resource.DataAuthorizable;
import org.apache.nifi.authorization.resource.DataTransferAuthorizable;
import org.apache.nifi.authorization.resource.OperationAuthorizable;
import org.apache.nifi.authorization.resource.ProvenanceDataAuthorizable;
+import org.apache.nifi.controller.FlowAnalysisRuleNode;
import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.nar.ExtensionDiscoveringManager;
import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.registry.flow.FlowRegistryClientNode;
import org.apache.nifi.web.controller.ControllerFacade;
+import org.apache.nifi.web.dao.FlowAnalysisRuleDAO;
+import org.apache.nifi.web.dao.FlowRegistryDAO;
import org.apache.nifi.web.dao.ProcessorDAO;
import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -36,20 +41,11 @@ import static org.mockito.Mockito.when;
public class StandardAuthorizableLookupTest {
- @Test
- public void testGetAuthorizableFromResource() {
- final ExtensionManager extensionManager =
mock(ExtensionDiscoveringManager.class);
- final ControllerFacade controllerFacade = mock(ControllerFacade.class);
-
when(controllerFacade.getExtensionManager()).thenReturn(extensionManager);
+ private static final String COMPONENT_ID = "id";
- final ProcessorDAO processorDAO = mock(ProcessorDAO.class);
- final ProcessorNode processorNode = mock(ProcessorNode.class);
-
- when(processorDAO.getProcessor(eq("id"))).thenReturn(processorNode);
-
- final StandardAuthorizableLookup lookup = new
StandardAuthorizableLookup();
- lookup.setProcessorDAO(processorDAO);
- lookup.setControllerFacade(controllerFacade);
+ @Test
+ void testGetAuthorizableFromResource() {
+ final StandardAuthorizableLookup lookup = getLookup();
Authorizable authorizable =
lookup.getAuthorizableFromResource("/processors/id");
assertInstanceOf(ProcessorNode.class, authorizable);
@@ -74,4 +70,51 @@ public class StandardAuthorizableLookupTest {
assertInstanceOf(OperationAuthorizable.class, authorizable);
assertInstanceOf(ProcessorNode.class, ((OperationAuthorizable)
authorizable).getBaseAuthorizable());
}
+
+ @Test
+ void testGetAuthorizableFromResourceController() {
+ final StandardAuthorizableLookup lookup = getLookup();
+
+ final Authorizable authorizable =
lookup.getAuthorizableFromResource("/controller");
+ assertInstanceOf(ControllerFacade.class, authorizable);
+ }
+
+ @Test
+ void testGetAuthorizableFromResourceRegistryClient() {
+ final StandardAuthorizableLookup lookup = getLookup();
+ final FlowRegistryDAO flowRegistryDAO = mock(FlowRegistryDAO.class);
+ final FlowRegistryClientNode flowRegistryClientNode =
mock(FlowRegistryClientNode.class);
+
when(flowRegistryDAO.getFlowRegistryClient(eq(COMPONENT_ID))).thenReturn(flowRegistryClientNode);
+ lookup.setFlowRegistryDAO(flowRegistryDAO);
+
+ final Authorizable authorizable =
lookup.getAuthorizableFromResource("/controller/registry-clients/id");
+ assertEquals(flowRegistryClientNode, authorizable);
+ }
+
+ @Test
+ void testGetAuthorizableFromResourceFlowAnalysisRule() {
+ final StandardAuthorizableLookup lookup = getLookup();
+ final FlowAnalysisRuleDAO flowAnalysisRuleDAO =
mock(FlowAnalysisRuleDAO.class);
+ final FlowAnalysisRuleNode flowAnalysisRuleNode =
mock(FlowAnalysisRuleNode.class);
+
when(flowAnalysisRuleDAO.getFlowAnalysisRule(eq(COMPONENT_ID))).thenReturn(flowAnalysisRuleNode);
+ lookup.setFlowAnalysisRuleDAO(flowAnalysisRuleDAO);
+
+ final Authorizable authorizable =
lookup.getAuthorizableFromResource("/controller/flow-analysis-rules/id");
+ assertEquals(flowAnalysisRuleNode, authorizable);
+ }
+
+ private StandardAuthorizableLookup getLookup() {
+ final ExtensionManager extensionManager =
mock(ExtensionDiscoveringManager.class);
+ final ControllerFacade controllerFacade = mock(ControllerFacade.class);
+
when(controllerFacade.getExtensionManager()).thenReturn(extensionManager);
+
+ final ProcessorDAO processorDAO = mock(ProcessorDAO.class);
+ final ProcessorNode processorNode = mock(ProcessorNode.class);
+
when(processorDAO.getProcessor(eq(COMPONENT_ID))).thenReturn(processorNode);
+
+ final StandardAuthorizableLookup lookup = new
StandardAuthorizableLookup();
+ lookup.setProcessorDAO(processorDAO);
+ lookup.setControllerFacade(controllerFacade);
+ return lookup;
+ }
}