diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc b/nifi-docs/src/main/asciidoc/administration-guide.adoc index 98c1a95bdc..caffbf419d 100644 --- a/nifi-docs/src/main/asciidoc/administration-guide.adoc +++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc @@ -925,6 +925,7 @@ The following tables summarize the global and component policies assigned to eac |modify the component | |* | | | | |view the data | |* | |* | |* |modify the data | |* | | | |* +|view provenance | | | |* | | |========================== @@ -1102,13 +1103,17 @@ Component level access policies govern the following component level authorizati |`resource="//" action="W"` |view the data -|Allows user to view metadata and content for this component through provenance data and flowfile queues in outbound connections +|Allows users to view metadata and content for this component through provenance data and flowfile queues in outbound connections |`resource="/data//" action="R"` |modify the data -|Allows user to empty flowfile queues in outbound connections and submit replays +|Allows users to empty flowfile queues in outbound connections and submit replays |`resource="/data//" action="W"` +|view provenance +|Allows users to view provenance data generated by this component +|`resource="/provenance-data//" action="R"` + |view the policies |Allows users to view the list of users who can view/modify a component |`resource="/policies//" action="R"` diff --git a/nifi-docs/src/main/asciidoc/user-guide.adoc b/nifi-docs/src/main/asciidoc/user-guide.adoc index e7806fb411..c99940f7d0 100644 --- a/nifi-docs/src/main/asciidoc/user-guide.adoc +++ b/nifi-docs/src/main/asciidoc/user-guide.adoc @@ -211,6 +211,7 @@ The available component-level access policies are: |modify the component |Allows users to modify component configuration details |view the data |Allows users to view metadata and content for this component through provenance data and flowfile queues in outbound connection |modify the data |Allows users to empty flowfile queues in outbound connections and to submit replays +|view provenance |Allows users to view provenance data generated by this component |view the policies |Allows users to view the list of users who can view and modify a component |modify the policies |Allows users to modify the list of users who can view and modify a component |retrieve data via site-to-site |Allows a port to receive data from NiFi instances @@ -2184,6 +2185,10 @@ search the information for specific items, and filter the search results. It is replay data at any point within the dataflow, and see a graphical representation of the data's lineage, or path through the flow. (These features are described in depth below.) +When authorization is enabled, accessessing Data Provenance information requires the 'query provenance' Global Policy as well as the 'view provenance' +Component Policy for the component which generated the event. In addition, access to event details which include FlowFile attributes and content require +the 'view the data' Component Policy for the component which generated the event. + image:provenance-annotated.png["Provenance Table"] [[provenance_events]] diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java b/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java index 0bbb190c80..1c9d1f6365 100644 --- a/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java +++ b/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java @@ -42,4 +42,14 @@ public interface ProvenanceAuthorizableFactory { */ Authorizable createRemoteDataAuthorizable(String remoteGroupPortId); + /** + * Generates an Authorizable object for the Provenance Data of the component with the given ID. + * + * @param componentId the ID of the component to which the Data belongs + * + * @return the Authorizable that can be use to authorize access to provenance events + * @throws ResourceNotFoundException if no component can be found with the given ID + */ + Authorizable createProvenanceDataAuthorizable(String componentId); + } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java index 6ee09fe167..d35aff06a6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java @@ -64,6 +64,7 @@ public final class RoleAccessPolicy { provenancePolicies.add(new RoleAccessPolicy(ResourceType.Provenance.getValue(), READ_ACTION)); if (rootGroupId != null) { provenancePolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION)); + provenancePolicies.add(new RoleAccessPolicy(ResourceType.ProvenanceData.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION)); } roleAccessPolicies.put(Role.ROLE_PROVENANCE, Collections.unmodifiableSet(provenancePolicies)); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAccessPolicyProviderTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAccessPolicyProviderTest.java index 3c9e4c563e..917643490c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAccessPolicyProviderTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAccessPolicyProviderTest.java @@ -341,12 +341,20 @@ public class FileAccessPolicyProviderTest { // verify user2's policies final Map> user2Policies = getResourceActions(policies, user2); - assertEquals(2, user2Policies.size()); + assertEquals(3, user2Policies.size()); assertTrue(user2Policies.containsKey(ResourceType.Provenance.getValue())); assertEquals(1, user2Policies.get(ResourceType.Provenance.getValue()).size()); assertTrue(user2Policies.get(ResourceType.Provenance.getValue()).contains(RequestAction.READ)); + assertTrue(user2Policies.containsKey(ResourceType.ProvenanceData.getValue() + "/process-groups/" + ROOT_GROUP_ID)); + assertEquals(1, user2Policies.get(ResourceType.ProvenanceData.getValue() + "/process-groups/" + ROOT_GROUP_ID).size()); + assertTrue(user2Policies.get(ResourceType.ProvenanceData.getValue() + "/process-groups/" + ROOT_GROUP_ID).contains(RequestAction.READ)); + + assertTrue(user2Policies.containsKey(ResourceType.Data.getValue() + "/process-groups/" + ROOT_GROUP_ID)); + assertEquals(1, user2Policies.get(ResourceType.Data.getValue() + "/process-groups/" + ROOT_GROUP_ID).size()); + assertTrue(user2Policies.get(ResourceType.Data.getValue() + "/process-groups/" + ROOT_GROUP_ID).contains(RequestAction.READ)); + // verify user3's policies final Map> user3Policies = getResourceActions(policies, user3); assertEquals(6, user3Policies.size()); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java index d434344a9c..9aeb05b59b 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java @@ -341,12 +341,20 @@ public class FileAuthorizerTest { // verify user2's policies final Map> user2Policies = getResourceActions(policies, user2); - assertEquals(2, user2Policies.size()); + assertEquals(3, user2Policies.size()); assertTrue(user2Policies.containsKey(ResourceType.Provenance.getValue())); assertEquals(1, user2Policies.get(ResourceType.Provenance.getValue()).size()); assertTrue(user2Policies.get(ResourceType.Provenance.getValue()).contains(RequestAction.READ)); + assertTrue(user2Policies.containsKey(ResourceType.ProvenanceData.getValue() + "/process-groups/" + ROOT_GROUP_ID)); + assertEquals(1, user2Policies.get(ResourceType.ProvenanceData.getValue() + "/process-groups/" + ROOT_GROUP_ID).size()); + assertTrue(user2Policies.get(ResourceType.ProvenanceData.getValue() + "/process-groups/" + ROOT_GROUP_ID).contains(RequestAction.READ)); + + assertTrue(user2Policies.containsKey(ResourceType.Data.getValue() + "/process-groups/" + ROOT_GROUP_ID)); + assertEquals(1, user2Policies.get(ResourceType.Data.getValue() + "/process-groups/" + ROOT_GROUP_ID).size()); + assertTrue(user2Policies.get(ResourceType.Data.getValue() + "/process-groups/" + ROOT_GROUP_ID).contains(RequestAction.READ)); + // verify user3's policies final Map> user3Policies = getResourceActions(policies, user3); assertEquals(6, user3Policies.size()); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceDataAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceDataAuthorizable.java new file mode 100644 index 0000000000..54e57669b7 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceDataAuthorizable.java @@ -0,0 +1,48 @@ +/* + * 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.resource; + +import org.apache.nifi.authorization.Resource; + +public class ProvenanceDataAuthorizable implements Authorizable, EnforcePolicyPermissionsThroughBaseResource { + private final Authorizable authorizable; + + public ProvenanceDataAuthorizable(final Authorizable authorizable) { + this.authorizable = authorizable; + } + + @Override + public Authorizable getBaseAuthorizable() { + return authorizable; + } + + @Override + public Authorizable getParentAuthorizable() { + if (authorizable.getParentAuthorizable() == null) { + return null; + } else { + return new ProvenanceDataAuthorizable(authorizable.getParentAuthorizable()); + } + } + + @Override + public Resource getResource() { + return ResourceFactory.getProvenanceDataResource(authorizable.getResource()); + } + + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java index 6f545f30db..f2cec027bb 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java @@ -108,6 +108,23 @@ public final class ResourceFactory { } }; + private final static Resource PROVENANCE_DATA_RESOURCE = new Resource() { + @Override + public String getIdentifier() { + return ResourceType.ProvenanceData.getValue(); + } + + @Override + public String getName() { + return "Provenance data for "; + } + + @Override + public String getSafeDescription() { + return "the provenance data for "; + } + }; + private final static Resource DATA_RESOURCE = new Resource() { @Override public String getIdentifier() { @@ -491,10 +508,10 @@ public final class ResourceFactory { } /** - * Gets a Resource for accessing a component's provenance events. + * Gets a Resource for accessing flowfile information * * @param resource The resource for the component being accessed - * @return The resource for the provenance of the component being accessed + * @return The resource for the data of the component being accessed */ public static Resource getDataResource(final Resource resource) { return new Resource() { @@ -515,6 +532,33 @@ public final class ResourceFactory { }; } + /** + * Gets a Resource for accessing provenance data. + * + * @param resource The resource for the component being accessed + * @return The resource for the provenance data being accessed + */ + public static Resource getProvenanceDataResource(final Resource resource) { + Objects.requireNonNull(resource, "The resource must be specified."); + + return new Resource() { + @Override + public String getIdentifier() { + return String.format("%s%s", PROVENANCE_DATA_RESOURCE.getIdentifier(), resource.getIdentifier()); + } + + @Override + public String getName() { + return PROVENANCE_DATA_RESOURCE.getName() + resource.getName(); + } + + @Override + public String getSafeDescription() { + return PROVENANCE_DATA_RESOURCE.getSafeDescription() + resource.getSafeDescription(); + } + }; + } + /** * Prevent outside instantiation. */ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java index 5973f6bb98..d2d3126ca3 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java @@ -29,6 +29,7 @@ public enum ResourceType { Processor("/processors"), ProcessGroup("/process-groups"), Provenance("/provenance"), + ProvenanceData("/provenance-data"), Data("/data"), Proxy("/proxy"), RemoteProcessGroup("/remote-process-groups"), diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/resource/ProvenanceDataAuthorizableTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/resource/ProvenanceDataAuthorizableTest.java new file mode 100644 index 0000000000..fcc5406d28 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/test/java/org/apache/nifi/authorization/resource/ProvenanceDataAuthorizableTest.java @@ -0,0 +1,117 @@ +/* + * 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.resource; + +import org.apache.nifi.authorization.AccessDeniedException; +import org.apache.nifi.authorization.AuthorizationRequest; +import org.apache.nifi.authorization.AuthorizationResult; +import org.apache.nifi.authorization.AuthorizationResult.Result; +import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.authorization.RequestAction; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.StandardNiFiUser.Builder; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentMatcher; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class ProvenanceDataAuthorizableTest { + + private static final String IDENTITY_1 = "identity-1"; + + private Authorizer testAuthorizer; + private ProvenanceDataAuthorizable testProvenanceDataAuthorizable; + + @Before + public void setup() { + Authorizable testProcessorAuthorizable; + testProcessorAuthorizable = mock(Authorizable.class); + when(testProcessorAuthorizable.getParentAuthorizable()).thenReturn(null); + when(testProcessorAuthorizable.getResource()).thenReturn(ResourceFactory.getComponentResource(ResourceType.Processor, "id", "name")); + + testAuthorizer = mock(Authorizer.class); + when(testAuthorizer.authorize(any(AuthorizationRequest.class))).then(invocation -> { + final AuthorizationRequest request = invocation.getArgumentAt(0, AuthorizationRequest.class); + + if (IDENTITY_1.equals(request.getIdentity())) { + return AuthorizationResult.approved(); + } + + return AuthorizationResult.denied(); + }); + + testProvenanceDataAuthorizable = new ProvenanceDataAuthorizable(testProcessorAuthorizable); + } + + @Test(expected = AccessDeniedException.class) + public void testAuthorizeNullUser() { + testProvenanceDataAuthorizable.authorize(testAuthorizer, RequestAction.READ, null, null); + } + + @Test + public void testCheckAuthorizationNullUser() { + final AuthorizationResult result = testProvenanceDataAuthorizable.checkAuthorization(testAuthorizer, RequestAction.READ, null, null); + assertEquals(Result.Denied, result.getResult()); + } + + @Test(expected = AccessDeniedException.class) + public void testAuthorizeUnauthorizedUser() { + final NiFiUser user = new Builder().identity("unknown").build(); + testProvenanceDataAuthorizable.authorize(testAuthorizer, RequestAction.READ, user, null); + } + + @Test + public void testCheckAuthorizationUnauthorizedUser() { + final NiFiUser user = new Builder().identity("unknown").build(); + final AuthorizationResult result = testProvenanceDataAuthorizable.checkAuthorization(testAuthorizer, RequestAction.READ, user, null); + assertEquals(Result.Denied, result.getResult()); + } + + @Test + public void testAuthorizedUser() { + final NiFiUser user = new Builder().identity(IDENTITY_1).build(); + testProvenanceDataAuthorizable.authorize(testAuthorizer, RequestAction.READ, user, null); + + verify(testAuthorizer, times(1)).authorize(argThat(new ArgumentMatcher() { + @Override + public boolean matches(Object o) { + return IDENTITY_1.equals(((AuthorizationRequest) o).getIdentity()); + } + })); + } + + @Test + public void testCheckAuthorizationUser() { + final NiFiUser user = new Builder().identity(IDENTITY_1).build(); + final AuthorizationResult result = testProvenanceDataAuthorizable.checkAuthorization(testAuthorizer, RequestAction.READ, user, null); + + assertEquals(Result.Approved, result.getResult()); + verify(testAuthorizer, times(1)).authorize(argThat(new ArgumentMatcher() { + @Override + public boolean matches(Object o) { + return IDENTITY_1.equals(((AuthorizationRequest) o).getIdentity()); + } + })); + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java index ed56694fd0..e7623e5731 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java @@ -32,6 +32,7 @@ import org.apache.nifi.authorization.RequestAction; import org.apache.nifi.authorization.Resource; import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.authorization.resource.DataAuthorizable; +import org.apache.nifi.authorization.resource.ProvenanceDataAuthorizable; import org.apache.nifi.authorization.resource.ResourceFactory; import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.bundle.Bundle; @@ -4966,6 +4967,38 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R return authorizable; } + @Override + public Authorizable createProvenanceDataAuthorizable(String componentId) { + final String rootGroupId = getRootGroupId(); + + // Provenance Events are generated only by connectable components, with the exception of DOWNLOAD events, + // which have the root process group's identifier assigned as the component ID, and DROP events, which + // could have the connection identifier assigned as the component ID. So, we check if the component ID + // is set to the root group and otherwise assume that the ID is that of a connectable or connection. + final ProvenanceDataAuthorizable authorizable; + if (rootGroupId.equals(componentId)) { + authorizable = new ProvenanceDataAuthorizable(getRootGroup()); + } else { + // check if the component is a connectable, this should be the case most often + final Connectable connectable = getRootGroup().findLocalConnectable(componentId); + if (connectable == null) { + // if the component id is not a connectable then consider a connection + final Connection connection = getRootGroup().findConnection(componentId); + + if (connection == null) { + throw new ResourceNotFoundException("The component that generated this event is no longer part of the data flow."); + } else { + // authorizable for connection data is associated with the source connectable + authorizable = new ProvenanceDataAuthorizable(connection.getSource()); + } + } else { + authorizable = new ProvenanceDataAuthorizable(connectable); + } + } + + return authorizable; + } + @Override public List getFlowChanges(final int firstActionId, final int maxActions) { final History history = auditService.getActions(firstActionId, maxActions); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java index 0468f23b3f..bbdd9e0b28 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java @@ -22,6 +22,7 @@ import org.apache.nifi.authorization.resource.AccessPolicyAuthorizable; import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.authorization.resource.DataAuthorizable; import org.apache.nifi.authorization.resource.DataTransferAuthorizable; +import org.apache.nifi.authorization.resource.ProvenanceDataAuthorizable; import org.apache.nifi.authorization.resource.ResourceFactory; import org.apache.nifi.authorization.resource.ResourceType; import org.apache.nifi.authorization.resource.RestrictedComponentsAuthorizableFactory; @@ -480,8 +481,8 @@ class StandardAuthorizableLookup implements AuthorizableLookup { throw new ResourceNotFoundException("Unrecognized resource: " + resource); } - // if this is a policy or a provenance event resource, there should be another resource type - if (ResourceType.Policy.equals(resourceType) || ResourceType.Data.equals(resourceType) || ResourceType.DataTransfer.equals(resourceType)) { + // if this is a policy, data or a provenance event resource, there should be another resource type + if (ResourceType.Policy.equals(resourceType) || ResourceType.Data.equals(resourceType) || ResourceType.DataTransfer.equals(resourceType) || ResourceType.ProvenanceData.equals(resourceType)) { final ResourceType primaryResourceType = resourceType; resourceType = null; @@ -503,6 +504,8 @@ class StandardAuthorizableLookup implements AuthorizableLookup { return new AccessPolicyAuthorizable(getAccessPolicy(resourceType, resource)); } else if (ResourceType.Data.equals(primaryResourceType)) { return new DataAuthorizable(getAccessPolicy(resourceType, resource)); + } else if (ResourceType.ProvenanceData.equals(primaryResourceType)) { + return new ProvenanceDataAuthorizable(getAccessPolicy(resourceType, resource)); } else { return new DataTransferAuthorizable(getAccessPolicy(resourceType, resource)); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java index d00b73a92b..5fc1fc53eb 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java @@ -1395,6 +1395,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final List resources = new ArrayList<>(); resources.add(componentResource); resources.add(ResourceFactory.getDataResource(componentResource)); + resources.add(ResourceFactory.getProvenanceDataResource(componentResource)); resources.add(ResourceFactory.getDataTransferResource(componentResource)); resources.add(ResourceFactory.getPolicyResource(componentResource)); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java index 1d9be9c882..c45aa80c59 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java @@ -845,6 +845,7 @@ public class ControllerFacade implements Authorizable { final Resource rootResource = root.getResource(); resources.add(rootResource); resources.add(ResourceFactory.getDataResource(rootResource)); + resources.add(ResourceFactory.getProvenanceDataResource(rootResource)); resources.add(ResourceFactory.getPolicyResource(rootResource)); // add each processor @@ -852,6 +853,7 @@ public class ControllerFacade implements Authorizable { final Resource processorResource = processor.getResource(); resources.add(processorResource); resources.add(ResourceFactory.getDataResource(processorResource)); + resources.add(ResourceFactory.getProvenanceDataResource(processorResource)); resources.add(ResourceFactory.getPolicyResource(processorResource)); } @@ -867,6 +869,7 @@ public class ControllerFacade implements Authorizable { final Resource processGroupResource = processGroup.getResource(); resources.add(processGroupResource); resources.add(ResourceFactory.getDataResource(processGroupResource)); + resources.add(ResourceFactory.getProvenanceDataResource(processGroupResource)); resources.add(ResourceFactory.getPolicyResource(processGroupResource)); } @@ -875,6 +878,7 @@ public class ControllerFacade implements Authorizable { final Resource remoteProcessGroupResource = remoteProcessGroup.getResource(); resources.add(remoteProcessGroupResource); resources.add(ResourceFactory.getDataResource(remoteProcessGroupResource)); + resources.add(ResourceFactory.getProvenanceDataResource(remoteProcessGroupResource)); resources.add(ResourceFactory.getPolicyResource(remoteProcessGroupResource)); } @@ -1077,7 +1081,10 @@ public class ControllerFacade implements Authorizable { if (includeResults || queryResult.isFinished()) { final List events = new ArrayList<>(); for (final ProvenanceEventRecord record : queryResult.getMatchingEvents()) { - events.add(createProvenanceEventDto(record, Boolean.TRUE.equals(summarize))); + final ProvenanceEventDTO dto = createProvenanceEventDto(record, Boolean.TRUE.equals(summarize)); + if (dto != null) { + events.add(dto); + } } resultsDto.setProvenanceEvents(events); } @@ -1270,7 +1277,7 @@ public class ControllerFacade implements Authorizable { } // authorize the replay - authorizeReplay(originalEvent); + authorizeData(originalEvent); // replay the flow file final ProvenanceEventRecord event = flowController.replayFlowFile(originalEvent, user); @@ -1303,13 +1310,7 @@ public class ControllerFacade implements Authorizable { final Map eventAttributes = event.getAttributes(); - // ensure we can read the data - final AuthorizationResult result = dataAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, eventAttributes); - if (!Result.Approved.equals(result.getResult())) { - return result; - } - - // ensure we can write the data + // ensure we can write the data; read the data should have been checked already return dataAuthorizable.checkAuthorization(authorizer, RequestAction.WRITE, user, eventAttributes); } @@ -1318,7 +1319,7 @@ public class ControllerFacade implements Authorizable { * * @param event event */ - private void authorizeReplay(final ProvenanceEventRecord event) { + private void authorizeData(final ProvenanceEventRecord event) { // if the connection id isn't specified, then the replay wouldn't be available anyways and we have nothing to authorize against so deny it` if (event.getSourceQueueIdentifier() == null) { throw new AccessDeniedException("The connection id in the provenance event is unknown."); @@ -1338,6 +1339,67 @@ public class ControllerFacade implements Authorizable { dataAuthorizable.authorize(authorizer, RequestAction.WRITE, user, eventAttributes); } + private AuthorizationResult checkAuthorizationForData(ProvenanceEventRecord event) { + final NiFiUser user = NiFiUserUtils.getNiFiUser(); + final Authorizable dataAuthorizable; + if (event.isRemotePortType()) { + dataAuthorizable = flowController.createRemoteDataAuthorizable(event.getComponentId()); + } else { + dataAuthorizable = flowController.createLocalDataAuthorizable(event.getComponentId()); + } + + final Map eventAttributes = event.getAttributes(); + + // ensure we can read the data + return dataAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, eventAttributes); + } + + private AuthorizationResult checkAuthorizationForProvenanceData(final ProvenanceEventRecord event) { + final ProcessGroup rootGroup = flowController.getGroup(getRootGroupId()); + final NiFiUser user = NiFiUserUtils.getNiFiUser(); + final String componentId = event.getComponentId(); + Connectable connectable; + String targetId = null; + // check if the component is the rootGroup + if (getRootGroupId().equals(componentId)) { + targetId = componentId; + } + if (targetId == null) { + // check if the component is a processor + connectable = rootGroup.findProcessor(componentId); + if (connectable == null) { + // if the component id is not a processor then consider a connection + connectable = rootGroup.findConnection(componentId).getSource(); + + if (connectable == null) { + throw new ResourceNotFoundException("The component that generated this event is no longer part of the data flow"); + } + } + targetId = connectable.getIdentifier(); + } + final Authorizable provenanceDataAuthorizable = flowController.createProvenanceDataAuthorizable(targetId); + + return provenanceDataAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user); + } + + private AuthorizationResult checkConnectableAuthorization(final String componentId) { + final ProcessGroup rootGroup = flowController.getGroup(getRootGroupId()); + final NiFiUser user = NiFiUserUtils.getNiFiUser(); + if (rootGroup.getIdentifier().equals(componentId)) { + return rootGroup.checkAuthorization(authorizer, RequestAction.READ, user); + } + Connectable connectable = rootGroup.findProcessor(componentId); + if (connectable == null) { + // if the component id is not a processor then consider a connection + connectable = rootGroup.findConnection(componentId).getSource(); + + if (connectable == null) { + throw new ResourceNotFoundException("The component that generated this event is no longer part of the data flow"); + } + } + return connectable.checkAuthorization(authorizer, RequestAction.READ, user); + } + /** * Get the provenance event with the specified event id. * @@ -1346,21 +1408,11 @@ public class ControllerFacade implements Authorizable { */ public ProvenanceEventDTO getProvenanceEvent(final Long eventId) { try { - final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId); + final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId, NiFiUserUtils.getNiFiUser()); if (event == null) { throw new ResourceNotFoundException("Unable to find the specified event."); } - // get the flowfile attributes and authorize the event - final Map attributes = event.getAttributes(); - final Authorizable dataAuthorizable; - if (event.isRemotePortType()) { - dataAuthorizable = flowController.createRemoteDataAuthorizable(event.getComponentId()); - } else { - dataAuthorizable = flowController.createLocalDataAuthorizable(event.getComponentId()); - } - dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser(), attributes); - // convert the event return createProvenanceEventDto(event, false); } catch (final IOException ioe) { @@ -1375,6 +1427,11 @@ public class ControllerFacade implements Authorizable { * @return event */ private ProvenanceEventDTO createProvenanceEventDto(final ProvenanceEventRecord event, final boolean summarize) { + // do not generate DTO if not authorized + final AuthorizationResult provenanceResult = checkAuthorizationForProvenanceData(event); + if (Result.Denied.equals(provenanceResult.getResult())) { + return null; + } final ProvenanceEventDTO dto = new ProvenanceEventDTO(); dto.setId(String.valueOf(event.getEventId())); dto.setEventId(event.getEventId()); @@ -1429,7 +1486,6 @@ public class ControllerFacade implements Authorizable { // additional event details dto.setAlternateIdentifierUri(event.getAlternateIdentifierUri()); - dto.setAttributes(attributes); dto.setTransitUri(event.getTransitUri()); dto.setSourceSystemFlowFileId(event.getSourceSystemFlowFileIdentifier()); dto.setRelationship(event.getRelationship()); @@ -1437,36 +1493,44 @@ public class ControllerFacade implements Authorizable { final ContentAvailability contentAvailability = flowController.getContentAvailability(event); - // content - dto.setContentEqual(contentAvailability.isContentSame()); - dto.setInputContentAvailable(contentAvailability.isInputAvailable()); - dto.setInputContentClaimSection(event.getPreviousContentClaimSection()); - dto.setInputContentClaimContainer(event.getPreviousContentClaimContainer()); - dto.setInputContentClaimIdentifier(event.getPreviousContentClaimIdentifier()); - dto.setInputContentClaimOffset(event.getPreviousContentClaimOffset()); - dto.setInputContentClaimFileSizeBytes(event.getPreviousFileSize()); - dto.setOutputContentAvailable(contentAvailability.isOutputAvailable()); - dto.setOutputContentClaimSection(event.getContentClaimSection()); - dto.setOutputContentClaimContainer(event.getContentClaimContainer()); - dto.setOutputContentClaimIdentifier(event.getContentClaimIdentifier()); - dto.setOutputContentClaimOffset(event.getContentClaimOffset()); - dto.setOutputContentClaimFileSize(FormatUtils.formatDataSize(event.getFileSize())); - dto.setOutputContentClaimFileSizeBytes(event.getFileSize()); + // set flowfile attributes and content only if approved for view the data + final AuthorizationResult dataResult = checkAuthorizationForData(event); + if (Result.Approved.equals(dataResult.getResult())) { + // attributes + dto.setAttributes(attributes); - // format the previous file sizes if possible - if (event.getPreviousFileSize() != null) { - dto.setInputContentClaimFileSize(FormatUtils.formatDataSize(event.getPreviousFileSize())); + // content + dto.setContentEqual(contentAvailability.isContentSame()); + dto.setInputContentAvailable(contentAvailability.isInputAvailable()); + dto.setInputContentClaimSection(event.getPreviousContentClaimSection()); + dto.setInputContentClaimContainer(event.getPreviousContentClaimContainer()); + dto.setInputContentClaimIdentifier(event.getPreviousContentClaimIdentifier()); + dto.setInputContentClaimOffset(event.getPreviousContentClaimOffset()); + dto.setInputContentClaimFileSizeBytes(event.getPreviousFileSize()); + dto.setOutputContentAvailable(contentAvailability.isOutputAvailable()); + dto.setOutputContentClaimSection(event.getContentClaimSection()); + dto.setOutputContentClaimContainer(event.getContentClaimContainer()); + dto.setOutputContentClaimIdentifier(event.getContentClaimIdentifier()); + dto.setOutputContentClaimOffset(event.getContentClaimOffset()); + dto.setOutputContentClaimFileSize(FormatUtils.formatDataSize(event.getFileSize())); + dto.setOutputContentClaimFileSizeBytes(event.getFileSize()); + + // format the previous file sizes if possible + if (event.getPreviousFileSize() != null) { + dto.setInputContentClaimFileSize(FormatUtils.formatDataSize(event.getPreviousFileSize())); + } + + // determine if authorized for event replay + // this authorization is for data write only; ensure data read was approved + final AuthorizationResult replayAuthorized = checkAuthorizationForReplay(event); + + // replay + dto.setReplayAvailable(contentAvailability.isReplayable() && Result.Approved.equals(replayAuthorized.getResult())); + dto.setReplayExplanation(contentAvailability.isReplayable() + && !Result.Approved.equals(replayAuthorized.getResult()) ? replayAuthorized.getExplanation() : contentAvailability.getReasonNotReplayable()); + dto.setSourceConnectionIdentifier(event.getSourceQueueIdentifier()); } - // determine if authorized for event replay - final AuthorizationResult replayAuthorized = checkAuthorizationForReplay(event); - - // replay - dto.setReplayAvailable(contentAvailability.isReplayable() && Result.Approved.equals(replayAuthorized.getResult())); - dto.setReplayExplanation(contentAvailability.isReplayable() - && !Result.Approved.equals(replayAuthorized.getResult()) ? replayAuthorized.getExplanation() : contentAvailability.getReasonNotReplayable()); - dto.setSourceConnectionIdentifier(event.getSourceQueueIdentifier()); - // event duration if (event.getEventDuration() >= 0) { dto.setEventDuration(event.getEventDuration()); @@ -1494,18 +1558,29 @@ public class ControllerFacade implements Authorizable { private void setComponentDetails(final ProvenanceEventDTO dto) { final ProcessGroup root = flowController.getGroup(flowController.getRootGroupId()); + final AuthorizationResult componentResult = checkConnectableAuthorization(dto.getComponentId()); final Connectable connectable = root.findLocalConnectable(dto.getComponentId()); if (connectable != null) { dto.setGroupId(connectable.getProcessGroup().getIdentifier()); - dto.setComponentName(connectable.getName()); + if (Result.Denied.equals(componentResult.getResult())) { + dto.setComponentType("Processor"); + dto.setComponentName(dto.getComponentId()); + } else { + dto.setComponentName(connectable.getName()); + } return; } final RemoteGroupPort remoteGroupPort = root.findRemoteGroupPort(dto.getComponentId()); if (remoteGroupPort != null) { dto.setGroupId(remoteGroupPort.getProcessGroupIdentifier()); - dto.setComponentName(remoteGroupPort.getName()); + if (Result.Denied.equals(componentResult.getResult())) { + dto.setComponentType("RemoteGroupPort"); + dto.setComponentName(dto.getComponentId()); + } else { + dto.setComponentName(remoteGroupPort.getName()); + } return; } @@ -1513,14 +1588,17 @@ public class ControllerFacade implements Authorizable { if (connection != null) { dto.setGroupId(connection.getProcessGroup().getIdentifier()); - String name = connection.getName(); - final Collection relationships = connection.getRelationships(); - if (StringUtils.isBlank(name) && CollectionUtils.isNotEmpty(relationships)) { - name = StringUtils.join(relationships.stream().map(relationship -> relationship.getName()).collect(Collectors.toSet()), ", "); + if (Result.Denied.equals(componentResult.getResult())) { + dto.setComponentType("Connection"); + dto.setComponentName(dto.getComponentId()); + } else { + String name = connection.getName(); + final Collection relationships = connection.getRelationships(); + if (StringUtils.isBlank(name) && CollectionUtils.isNotEmpty(relationships)) { + name = StringUtils.join(relationships.stream().map(relationship -> relationship.getName()).collect(Collectors.toSet()), ", "); + } + dto.setComponentName(name); } - dto.setComponentName(name); - - return; } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java index 2dbd1ca18e..5bebe9ae22 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java @@ -732,7 +732,7 @@ public final class SnippetUtils { /** * Clones all the component specified policies for the specified original component. This will include the component resource, data resource - * for the component, data transfer resource for the component, and policy resource for the component. + * for the component, view provenance for the component, data transfer resource for the component, and policy resource for the component. * * @param originalComponentResource original component resource * @param clonedComponentResource cloned component resource @@ -746,6 +746,7 @@ public final class SnippetUtils { final Map resources = new HashMap<>(); resources.put(originalComponentResource, clonedComponentResource); resources.put(ResourceFactory.getDataResource(originalComponentResource), ResourceFactory.getDataResource(clonedComponentResource)); + resources.put(ResourceFactory.getProvenanceDataResource(originalComponentResource), ResourceFactory.getProvenanceDataResource(clonedComponentResource)); resources.put(ResourceFactory.getDataTransferResource(originalComponentResource), ResourceFactory.getDataTransferResource(clonedComponentResource)); resources.put(ResourceFactory.getPolicyResource(originalComponentResource), ResourceFactory.getPolicyResource(clonedComponentResource)); @@ -829,7 +830,7 @@ public final class SnippetUtils { /** * Attempts to roll back all policies for the specified component. This includes the component resource, data resource - * for the component, data transfer resource for the component, and policy resource for the component. + * for the component, view provenance resource for the component, data transfer resource for the component, and policy resource for the component. * * @param componentResource component resource */ @@ -841,6 +842,7 @@ public final class SnippetUtils { final List resources = new ArrayList<>(); resources.add(componentResource); resources.add(ResourceFactory.getDataResource(componentResource)); + resources.add(ResourceFactory.getProvenanceDataResource(componentResource)); resources.add(ResourceFactory.getDataTransferResource(componentResource)); resources.add(ResourceFactory.getPolicyResource(componentResource)); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js index 3105d41970..177a765e44 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js @@ -532,11 +532,15 @@ }, { text: 'view the data', value: 'read-data', - description: 'Allows users to view metadata and content for this component through provenance data and flowfile queues in outbound connections' + description: 'Allows users to view metadata and content for this component through flowfile queues in outbound connections' }, { text: 'modify the data', value: 'write-data', description: 'Allows users to empty flowfile queues in outbound connections and submit replays' + }, { + text: 'view provenance', + value: 'read-provenance', + description: 'Allows users to view provenance data generated by this component' }, { text: 'receive data via site-to-site', value: 'write-receive-data', @@ -570,6 +574,9 @@ } else if (option.value === 'write-data') { $('#selected-policy-action').text('write'); resource = ('data/' + resource); + } else if (option.value === 'read-provenance') { + $('#selected-policy-action').text('read'); + resource = ('provenance-data/' + resource); } else if (option.value === 'read-policies') { $('#selected-policy-action').text('read'); resource = ('policies/' + resource); @@ -1470,6 +1477,9 @@ .combo('setOptionEnabled', { value: 'read-data' }, false) + .combo('setOptionEnabled', { + value: 'read-provenance' + }, false) .combo('setOptionEnabled', { value: 'write-data' }, false) @@ -1514,6 +1524,9 @@ .combo('setOptionEnabled', { value: 'read-data' }, false) + .combo('setOptionEnabled', { + value: 'read-provenance' + }, false) .combo('setOptionEnabled', { value: 'write-data' }, false) @@ -1558,6 +1571,9 @@ .combo('setOptionEnabled', { value: 'read-data' }, false) + .combo('setOptionEnabled', { + value: 'read-provenance' + }, false) .combo('setOptionEnabled', { value: 'write-data' }, false) @@ -1598,6 +1614,9 @@ .combo('setOptionEnabled', { value: 'read-data' }, true) + .combo('setOptionEnabled', { + value: 'read-provenance' + }, true) .combo('setOptionEnabled', { value: 'write-data' }, true); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js index 3229b8288c..af96df4141 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js @@ -1301,6 +1301,17 @@ provenanceTableCtrl.getEventDetails(eventId, clusterNodeId).done(function (response) { var event = response.provenanceEvent; + // Hide or show dialog tabs as required if base properties are defined + var tabs = $('#event-details-tabs').find("li"); + $(tabs).each(function(index) { + if ((event["attributes"] === undefined && index == 1) || + (event["inputContentAvailable"] === undefined && index ==2)) { + $(this).hide(); + } else { + $(this).show(); + } + }); + // update the event details $('#provenance-event-id').text(event.eventId); $('#provenance-event-time').html(nfCommon.formatValue(event.eventTime)).ellipsis(); diff --git a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java index 6f48e50669..d1e5ad0265 100644 --- a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java +++ b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java @@ -385,11 +385,7 @@ public class PersistentProvenanceRepository implements ProvenanceRepository { final Authorizable eventAuthorizable; try { - if (event.isRemotePortType()) { - eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId()); - } else { - eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId()); - } + eventAuthorizable = resourceFactory.createProvenanceDataAuthorizable(event.getComponentId()); } catch (final ResourceNotFoundException rnfe) { return false; } @@ -403,13 +399,8 @@ public class PersistentProvenanceRepository implements ProvenanceRepository { return; } - final Authorizable eventAuthorizable; - if (event.isRemotePortType()) { - eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId()); - } else { - eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId()); - } - eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes()); + final Authorizable eventAuthorizable = resourceFactory.createProvenanceDataAuthorizable(event.getComponentId()); + eventAuthorizable.authorize(authorizer, RequestAction.READ, user); } public List filterUnauthorizedEvents(final List events, final NiFiUser user) { diff --git a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/WriteAheadProvenanceRepository.java b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/WriteAheadProvenanceRepository.java index ab7dfaed6f..c69ef03621 100644 --- a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/WriteAheadProvenanceRepository.java +++ b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/WriteAheadProvenanceRepository.java @@ -226,13 +226,8 @@ public class WriteAheadProvenanceRepository implements ProvenanceRepository { return; } - final Authorizable eventAuthorizable; - if (event.isRemotePortType()) { - eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId()); - } else { - eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId()); - } - eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes()); + final Authorizable eventAuthorizable = resourceFactory.createProvenanceDataAuthorizable(event.getComponentId()); + eventAuthorizable.authorize(authorizer, RequestAction.READ, user); } diff --git a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/authorization/UserEventAuthorizer.java b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/authorization/UserEventAuthorizer.java index 5126b7e678..70cd1251cc 100644 --- a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/authorization/UserEventAuthorizer.java +++ b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/authorization/UserEventAuthorizer.java @@ -46,16 +46,12 @@ public class UserEventAuthorizer implements EventAuthorizer { final Authorizable eventAuthorizable; try { - if (event.isRemotePortType()) { - eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId()); - } else { - eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId()); - } + eventAuthorizable = resourceFactory.createProvenanceDataAuthorizable(event.getComponentId()); } catch (final ResourceNotFoundException rnfe) { return false; } - final AuthorizationResult result = eventAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, event.getAttributes()); + final AuthorizationResult result = eventAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user); return Result.Approved.equals(result.getResult()); } @@ -65,12 +61,7 @@ public class UserEventAuthorizer implements EventAuthorizer { return; } - final Authorizable eventAuthorizable; - if (event.isRemotePortType()) { - eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId()); - } else { - eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId()); - } - eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes()); + final Authorizable eventAuthorizable = resourceFactory.createProvenanceDataAuthorizable(event.getComponentId()); + eventAuthorizable.authorize(authorizer, RequestAction.READ, user); } } diff --git a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java index 1ac6723414..4f627bb792 100644 --- a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java +++ b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java @@ -262,11 +262,7 @@ public class VolatileProvenanceRepository implements ProvenanceRepository { final Authorizable eventAuthorizable; try { - if (event.isRemotePortType()) { - eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId()); - } else { - eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId()); - } + eventAuthorizable = resourceFactory.createProvenanceDataAuthorizable(event.getComponentId()); } catch (final ResourceNotFoundException rnfe) { return false; } @@ -280,13 +276,8 @@ public class VolatileProvenanceRepository implements ProvenanceRepository { return; } - final Authorizable eventAuthorizable; - if (event.isRemotePortType()) { - eventAuthorizable = resourceFactory.createRemoteDataAuthorizable(event.getComponentId()); - } else { - eventAuthorizable = resourceFactory.createLocalDataAuthorizable(event.getComponentId()); - } - eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes()); + final Authorizable eventAuthorizable = resourceFactory.createProvenanceDataAuthorizable(event.getComponentId()); + eventAuthorizable.authorize(authorizer, RequestAction.READ, user); } private Filter createFilter(final Query query, final NiFiUser user) {