You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ma...@apache.org on 2016/07/26 18:15:55 UTC
[2/2] nifi git commit: NIFI-2346: - Introducing data resource for
authorizing provenance events and queue listing. - Authorizing entire proxy
chain for data resource and data transfer resource. NIFI-2338: - Ensuring
that replay authorization only happens
NIFI-2346:
- Introducing data resource for authorizing provenance events and queue listing.
- Authorizing entire proxy chain for data resource and data transfer resource.
NIFI-2338:
- Ensuring that replay authorization only happens once.
- Allowing users with access to policies for a component to be able to access all policies for that component.
-- Includes the component, data, data transfers, and policies.
- Fixing drop request completion to update the correct queued field.
- Fixing access control check for listing and emptying queues.
- Reseting selected policy when re-opening the policy management page.
- Fixing button/link visibility for available actions in policy management page.
- Fixing policy issues with policy removal when the underlying component is deleted.
- Updating file authorizer seeding to grant data access to node's in the cluster.
This closes #720.
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/69586d8b
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/69586d8b
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/69586d8b
Branch: refs/heads/master
Commit: 69586d8bd00b0e1e6cc606411363851b75684554
Parents: c27763a
Author: Matt Gilman <ma...@gmail.com>
Authored: Tue Jul 26 11:21:22 2016 -0400
Committer: Mark Payne <ma...@hotmail.com>
Committed: Tue Jul 26 14:15:36 2016 -0400
----------------------------------------------------------------------
.../authorization/resource/Authorizable.java | 8 +
.../ProvenanceAuthorizableFactory.java | 7 +-
.../nifi/authorization/FileAuthorizer.java | 9 +
.../nifi/authorization/RoleAccessPolicy.java | 8 +-
.../nifi/authorization/FileAuthorizerTest.java | 6 +-
.../resource/AccessPolicyAuthorizable.java | 98 ++++++++--
.../resource/DataAuthorizable.java | 125 ++++++++++++
.../resource/DataTransferAuthorizable.java | 5 +-
...rcePolicyPermissionsThroughBaseResource.java | 38 ++++
.../resource/ProvenanceEventAuthorizable.java | 41 ----
.../authorization/resource/ResourceFactory.java | 12 +-
.../authorization/resource/ResourceType.java | 2 +-
.../nifi/authorization/user/NiFiUserUtils.java | 26 +++
.../org/apache/nifi/controller/Template.java | 19 +-
.../nifi/connectable/StandardConnection.java | 8 +
.../apache/nifi/controller/FlowController.java | 73 ++++---
.../nifi/authorization/AuthorizableLookup.java | 7 +
.../StandardAuthorizableLookup.java | 17 +-
.../nifi/web/StandardNiFiContentAccess.java | 12 +-
.../nifi/web/StandardNiFiServiceFacade.java | 106 +++++-----
.../nifi/web/api/AccessPolicyResource.java | 10 +-
.../nifi/web/api/FlowFileQueueResource.java | 75 ++++---
.../nifi/web/controller/ControllerFacade.java | 115 +++--------
.../apache/nifi/web/dao/AccessPolicyDAO.java | 13 +-
.../web/dao/impl/StandardConnectionDAO.java | 36 +---
.../impl/StandardPolicyBasedAuthorizerDAO.java | 5 +
.../nifi/web/security/ProxiedEntitiesUtils.java | 39 +---
.../nifi-web-ui/src/main/webapp/css/login.css | 2 +-
.../src/main/webapp/js/nf/canvas/nf-actions.js | 21 +-
.../main/webapp/js/nf/canvas/nf-context-menu.js | 8 -
.../webapp/js/nf/canvas/nf-policy-management.js | 194 ++++++++++++-------
.../PersistentProvenanceRepository.java | 4 +-
.../VolatileProvenanceRepository.java | 4 +-
33 files changed, 688 insertions(+), 465 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
----------------------------------------------------------------------
diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
index 09829a9..cc0d8fc 100644
--- a/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
+++ b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
@@ -69,6 +69,10 @@ public interface Authorizable {
* @return is authorized
*/
default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
+ if (user == null) {
+ return AuthorizationResult.denied("Unknown user");
+ }
+
final Map<String,String> userContext;
if (user.getClientAddress() != null && !user.getClientAddress().trim().isEmpty()) {
userContext = new HashMap<>();
@@ -128,6 +132,10 @@ public interface Authorizable {
* @param resourceContext resource context
*/
default void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
+ if (user == null) {
+ throw new AccessDeniedException("Unknown user");
+ }
+
final Map<String,String> userContext;
if (user.getClientAddress() != null && !user.getClientAddress().trim().isEmpty()) {
userContext = new HashMap<>();
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-framework-api/src/main/java/org/apache/nifi/provenance/ProvenanceAuthorizableFactory.java
----------------------------------------------------------------------
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 23d6b3d..9699041 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
@@ -23,13 +23,14 @@ import org.apache.nifi.web.ResourceNotFoundException;
public interface ProvenanceAuthorizableFactory {
/**
- * Generates an Authorizable object for the Provenance events of the component with the given ID
+ * Generates an Authorizable object for the Data of the component with the given ID. This includes
+ * provenance data and queue's on outgoing relationships.
*
- * @param componentId the ID of the component to which the Provenance events belong
+ * @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 createProvenanceAuthorizable(String componentId);
+ Authorizable createDataAuthorizable(String componentId);
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
index f571c32..99672b6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
@@ -276,6 +276,9 @@ public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
// grant the user read access to the root process group resource
if (rootGroupId != null) {
+ addAccessPolicy(authorizations, ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), READ_CODE);
+ addAccessPolicy(authorizations, ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), WRITE_CODE);
+
addAccessPolicy(authorizations, ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), READ_CODE);
addAccessPolicy(authorizations, ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), WRITE_CODE);
}
@@ -322,6 +325,12 @@ public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
// grant access to the proxy resource
addAccessPolicy(authorizations, ResourceType.Proxy.getValue(), jaxbNodeUser.getIdentifier(), READ_CODE);
addAccessPolicy(authorizations, ResourceType.Proxy.getValue(), jaxbNodeUser.getIdentifier(), WRITE_CODE);
+
+ // grant the user read/write access data of the root group
+ if (rootGroupId != null) {
+ addAccessPolicy(authorizations, ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, jaxbNodeUser.getIdentifier(), READ_CODE);
+ addAccessPolicy(authorizations, ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, jaxbNodeUser.getIdentifier(), WRITE_CODE);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java
----------------------------------------------------------------------
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 c8a0f53..867423e 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
@@ -63,7 +63,7 @@ public final class RoleAccessPolicy {
final Set<RoleAccessPolicy> provenancePolicies = new HashSet<>();
provenancePolicies.add(new RoleAccessPolicy(ResourceType.Provenance.getValue(), READ_ACTION));
if (rootGroupId != null) {
- provenancePolicies.add(new RoleAccessPolicy(ResourceType.ProvenanceEvent.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
+ provenancePolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
}
roleAccessPolicies.put(Role.ROLE_PROVENANCE, Collections.unmodifiableSet(provenancePolicies));
@@ -75,6 +75,8 @@ public final class RoleAccessPolicy {
if (rootGroupId != null) {
dfmPolicies.add(new RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
dfmPolicies.add(new RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, WRITE_ACTION));
+ dfmPolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
+ dfmPolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, WRITE_ACTION));
}
roleAccessPolicies.put(Role.ROLE_DFM, Collections.unmodifiableSet(dfmPolicies));
@@ -93,6 +95,10 @@ public final class RoleAccessPolicy {
final Set<RoleAccessPolicy> proxyPolicies = new HashSet<>();
proxyPolicies.add(new RoleAccessPolicy(ResourceType.Proxy.getValue(), READ_ACTION));
proxyPolicies.add(new RoleAccessPolicy(ResourceType.Proxy.getValue(), WRITE_ACTION));
+ if (rootGroupId != null) {
+ proxyPolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
+ proxyPolicies.add(new RoleAccessPolicy(ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, WRITE_ACTION));
+ }
roleAccessPolicies.put(Role.ROLE_PROXY, Collections.unmodifiableSet(proxyPolicies));
final Set<RoleAccessPolicy> nifiPolicies = new HashSet<>();
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
----------------------------------------------------------------------
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 d1cf0c4..e5d6a54 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
@@ -254,7 +254,7 @@ public class FileAuthorizerTest {
// verify user3's policies
final Map<String,Set<RequestAction>> user3Policies = getResourceActions(policies, user3);
- assertEquals(4, user3Policies.size());
+ assertEquals(5, user3Policies.size());
assertTrue(user3Policies.containsKey(ResourceType.Flow.getValue()));
assertEquals(1, user3Policies.get(ResourceType.Flow.getValue()).size());
@@ -286,7 +286,7 @@ public class FileAuthorizerTest {
// verify user5's policies
final Map<String,Set<RequestAction>> user5Policies = getResourceActions(policies, user5);
- assertEquals(1, user5Policies.size());
+ assertEquals(2, user5Policies.size());
assertTrue(user5Policies.containsKey(ResourceType.Proxy.getValue()));
assertEquals(2, user5Policies.get(ResourceType.Proxy.getValue()).size());
@@ -384,7 +384,7 @@ public class FileAuthorizerTest {
assertEquals(adminIdentity, adminUser.getIdentity());
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
- assertEquals(9, policies.size());
+ assertEquals(11, policies.size());
final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java
index 08583e1..041b982 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/AccessPolicyAuthorizable.java
@@ -16,12 +16,33 @@
*/
package org.apache.nifi.authorization.resource;
+import org.apache.nifi.authorization.AccessDeniedException;
+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.Resource;
+import org.apache.nifi.authorization.user.NiFiUser;
+
+import java.util.Map;
/**
* Authorizable for policies of an Authorizable.
*/
-public class AccessPolicyAuthorizable implements Authorizable {
+public class AccessPolicyAuthorizable implements Authorizable, EnforcePolicyPermissionsThroughBaseResource {
+
+ private static final Authorizable POLICIES_AUTHORIZABLE = new Authorizable() {
+ @Override
+ public Authorizable getParentAuthorizable() {
+ return null;
+ }
+
+ @Override
+ public Resource getResource() {
+ return ResourceFactory.getPoliciesResource();
+ }
+ };
+
final Authorizable authorizable;
public AccessPolicyAuthorizable(Authorizable authorizable) {
@@ -29,26 +50,73 @@ public class AccessPolicyAuthorizable implements Authorizable {
}
@Override
+ public Authorizable getBaseAuthorizable() {
+ return authorizable;
+ }
+
+ @Override
public Authorizable getParentAuthorizable() {
- if (authorizable.getParentAuthorizable() == null) {
- return new Authorizable() {
- @Override
- public Authorizable getParentAuthorizable() {
- return null;
- }
-
- @Override
- public Resource getResource() {
- return ResourceFactory.getPoliciesResource();
- }
- };
+ final Authorizable effectiveAuthorizable = getEffectiveAuthorizable();
+ if (effectiveAuthorizable.getParentAuthorizable() == null) {
+ return POLICIES_AUTHORIZABLE;
} else {
- return new AccessPolicyAuthorizable(authorizable.getParentAuthorizable());
+ return new AccessPolicyAuthorizable(effectiveAuthorizable.getParentAuthorizable());
}
}
@Override
public Resource getResource() {
- return ResourceFactory.getPolicyResource(authorizable.getResource());
+ return ResourceFactory.getPolicyResource(getEffectiveAuthorizable().getResource());
+ }
+
+ private Authorizable getEffectiveAuthorizable() {
+ // possibly consider the base resource if the authorizable uses it to enforce policy permissions
+ if (authorizable instanceof EnforcePolicyPermissionsThroughBaseResource) {
+ final Authorizable baseAuthorizable = ((EnforcePolicyPermissionsThroughBaseResource) authorizable).getBaseAuthorizable();
+
+ // if the base authorizable is for a policy, we don't want to use the base otherwise it would keep unwinding and would eventually
+ // evaluate to the policy of the component and not the policy of the policies for the component
+ if (baseAuthorizable instanceof AccessPolicyAuthorizable) {
+ return authorizable;
+ } else {
+ return baseAuthorizable;
+ }
+ } else {
+ return authorizable;
+ }
+ }
+
+ @Override
+ public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
+ if (user == null) {
+ throw new AccessDeniedException("Unknown user");
+ }
+
+ final AuthorizationResult resourceResult = Authorizable.super.checkAuthorization(authorizer, action, user, resourceContext);
+
+ // if we're denied from the resource try inheriting
+ if (Result.Denied.equals(resourceResult.getResult())) {
+ return getParentAuthorizable().checkAuthorization(authorizer, action, user, resourceContext);
+ } else {
+ return resourceResult;
+ }
+ }
+
+ @Override
+ public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
+ if (user == null) {
+ throw new AccessDeniedException("Unknown user");
+ }
+
+ try {
+ Authorizable.super.authorize(authorizer, action, user, resourceContext);
+ } catch (final AccessDeniedException resourceDenied) {
+ // if we're denied from the resource try inheriting
+ try {
+ getParentAuthorizable().authorize(authorizer, action, user, resourceContext);
+ } catch (final AccessDeniedException policiesDenied) {
+ throw resourceDenied;
+ }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataAuthorizable.java
new file mode 100644
index 0000000..cb0d0f1
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataAuthorizable.java
@@ -0,0 +1,125 @@
+/*
+ * 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.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.Resource;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserUtils;
+import org.apache.nifi.authorization.user.StandardNiFiUser;
+import org.apache.nifi.web.ResourceNotFoundException;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Authorizable for authorizing access to data. Data based authorizable requires authorization for the entire DN chain.
+ */
+public class DataAuthorizable implements Authorizable, EnforcePolicyPermissionsThroughBaseResource {
+ final Authorizable authorizable;
+
+ public DataAuthorizable(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 DataAuthorizable(authorizable.getParentAuthorizable());
+ }
+ }
+
+ @Override
+ public Resource getResource() {
+ return ResourceFactory.getDataResource(authorizable.getResource());
+ }
+
+ @Override
+ public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
+ if (user == null) {
+ return AuthorizationResult.denied("Unknown user");
+ }
+
+ AuthorizationResult result = null;
+
+ // calculate the dn chain
+ final List<String> dnChain = NiFiUserUtils.buildProxiedEntitiesChain(user);
+ for (final String identity : dnChain) {
+ try {
+ final String clientAddress = user.getIdentity().equals(identity) ? user.getClientAddress() : null;
+ final NiFiUser chainUser = new StandardNiFiUser(identity, clientAddress) {
+ @Override
+ public boolean isAnonymous() {
+ // allow current user to drive anonymous flag as anonymous users are never chained... supports single user case
+ return user.isAnonymous();
+ }
+ };
+
+ result = Authorizable.super.checkAuthorization(authorizer, action, chainUser, resourceContext);
+ } catch (final ResourceNotFoundException e) {
+ result = AuthorizationResult.denied("Unknown source component.");
+ }
+
+ if (!Result.Approved.equals(result.getResult())) {
+ break;
+ }
+ }
+
+ if (result == null) {
+ result = AuthorizationResult.denied();
+ }
+
+ return result;
+ }
+
+ @Override
+ public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
+ if (user == null) {
+ throw new AccessDeniedException("Unknown user");
+ }
+
+ // calculate the dn chain
+ final List<String> dnChain = NiFiUserUtils.buildProxiedEntitiesChain(user);
+ for (final String identity : dnChain) {
+ try {
+ final String clientAddress = user.getIdentity().equals(identity) ? user.getClientAddress() : null;
+ final NiFiUser chainUser = new StandardNiFiUser(identity, clientAddress) {
+ @Override
+ public boolean isAnonymous() {
+ // allow current user to drive anonymous flag as anonymous users are never chained... supports single user case
+ return user.isAnonymous();
+ }
+ };
+
+ Authorizable.super.authorize(authorizer, action, chainUser, resourceContext);
+ } catch (final ResourceNotFoundException e) {
+ throw new AccessDeniedException("Unknown source component.");
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java
index 53aecbc..21df4f8 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/DataTransferAuthorizable.java
@@ -19,12 +19,13 @@ package org.apache.nifi.authorization.resource;
import org.apache.nifi.authorization.Resource;
/**
- * Authorizable for policies of an Authorizable.
+ * Authorizable for authorizing data transfers.
*/
-public class DataTransferAuthorizable implements Authorizable {
+public class DataTransferAuthorizable extends DataAuthorizable implements EnforcePolicyPermissionsThroughBaseResource {
final Authorizable authorizable;
public DataTransferAuthorizable(Authorizable authorizable) {
+ super(authorizable);
this.authorizable = authorizable;
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java
new file mode 100644
index 0000000..115315f
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/EnforcePolicyPermissionsThroughBaseResource.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Defers permissions on policies to the policies of the base authorizable. Required because we don't
+ * want to change the enforcement of the policies on the authorizable. For example...
+ *
+ * if a user has permissions to /policies/input-ports/1234 then they have permissions to the following
+ *
+ * - the policy for /input-ports/1234 -> /policies/input-ports/1234
+ * - the policy for /data/input-ports/1234 -> /policies/data/input-ports/1234
+ * - the policy for /data-transfers/input-ports/1234 -> /policies/data-transfers/input-ports/1234
+ * - the policy for /policies/input-ports/1234 -> /policies/policies/input-ports/1234
+ */
+public interface EnforcePolicyPermissionsThroughBaseResource {
+
+ /**
+ * Returns the base authorizable. Cannot be null.
+ *
+ * @return base authorizable
+ */
+ Authorizable getBaseAuthorizable();
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceEventAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceEventAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceEventAuthorizable.java
deleted file mode 100644
index 153047e..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ProvenanceEventAuthorizable.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 ProvenanceEventAuthorizable implements Authorizable {
- final Authorizable authorizable;
-
- public ProvenanceEventAuthorizable(final Authorizable authorizable) {
- this.authorizable = authorizable;
- }
-
- @Override
- public Authorizable getParentAuthorizable() {
- if (authorizable.getParentAuthorizable() == null) {
- return null;
- } else {
- return new ProvenanceEventAuthorizable(authorizable.getParentAuthorizable());
- }
- }
-
- @Override
- public Resource getResource() {
- return ResourceFactory.getProvenanceEventResource(authorizable.getResource());
- }
-}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
----------------------------------------------------------------------
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 baa58ac..426e7fd 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
@@ -166,15 +166,15 @@ public final class ResourceFactory {
}
};
- private final static Resource PROVENANCE_EVENT_RESOURCE = new Resource() {
+ private final static Resource DATA_RESOURCE = new Resource() {
@Override
public String getIdentifier() {
- return ResourceType.ProvenanceEvent.getValue();
+ return ResourceType.Data.getValue();
}
@Override
public String getName() {
- return "Provenance Event";
+ return "Data";
}
};
@@ -567,16 +567,16 @@ public final class ResourceFactory {
* @param resource The resource for the component being accessed
* @return The resource for the provenance of the component being accessed
*/
- public static Resource getProvenanceEventResource(final Resource resource) {
+ public static Resource getDataResource(final Resource resource) {
return new Resource() {
@Override
public String getIdentifier() {
- return String.format("%s%s", PROVENANCE_EVENT_RESOURCE.getIdentifier(), resource.getIdentifier());
+ return String.format("%s%s", DATA_RESOURCE.getIdentifier(), resource.getIdentifier());
}
@Override
public String getName() {
- return "Provenance Events for " + resource.getName();
+ return "Data for " + resource.getName();
}
};
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
----------------------------------------------------------------------
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 bce270a..37fe018 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,7 +29,7 @@ public enum ResourceType {
Processor("/processors"),
ProcessGroup("/process-groups"),
Provenance("/provenance"),
- ProvenanceEvent("/provenance-events"),
+ Data("/data"),
Proxy("/proxy"),
RemoteProcessGroup("/remote-process-groups"),
ReportingTask("/reporting-tasks"),
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
index 4a75274..6a4776a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
@@ -20,6 +20,9 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Utility methods for retrieving information about the current application user.
*
@@ -56,4 +59,27 @@ public final class NiFiUserUtils {
return user.getIdentity();
}
}
+
+ /**
+ * Builds the proxy chain for the specified user.
+ *
+ * @param user The current user
+ * @return The proxy chain for that user in List form
+ */
+ public static List<String> buildProxiedEntitiesChain(final NiFiUser user) {
+ // calculate the dn chain
+ final List<String> proxyChain = new ArrayList<>();
+
+ // build the dn chain
+ NiFiUser chainedUser = user;
+ do {
+ // add the entry for this user
+ proxyChain.add(chainedUser.getIdentity());
+
+ // go to the next user in the chain
+ chainedUser = chainedUser.getChain();
+ } while (chainedUser != null);
+
+ return proxyChain;
+ }
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
index ecc9e6f..86a9f38 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
@@ -158,20 +158,26 @@ public class Template implements Authorizable {
}
@Override
- public void authorize(final Authorizer authorizer, final RequestAction action, final NiFiUser user) throws AccessDeniedException {
- final AuthorizationResult result = checkAuthorization(authorizer, action, true, user);
- if (Result.Denied.equals(result)) {
+ public void authorize(final Authorizer authorizer, final RequestAction action, final NiFiUser user, final Map<String, String> resourceContext) throws AccessDeniedException {
+ final AuthorizationResult result = checkAuthorization(authorizer, action, true, user, resourceContext);
+ if (Result.Denied.equals(result.getResult())) {
final String explanation = result.getExplanation() == null ? "Access is denied" : result.getExplanation();
throw new AccessDeniedException(explanation);
}
}
@Override
- public AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final NiFiUser user) {
- return checkAuthorization(authorizer, action, false, user);
+ public AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final NiFiUser user, final Map<String, String> resourceContext) {
+ return checkAuthorization(authorizer, action, false, user, resourceContext);
}
- private AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final boolean accessAttempt, final NiFiUser user) {
+ private AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final boolean accessAttempt,
+ final NiFiUser user, final Map<String, String> resourceContext) {
+
+ if (user == null) {
+ return AuthorizationResult.denied("Unknown user");
+ }
+
final Map<String,String> userContext;
if (!StringUtils.isBlank(user.getClientAddress())) {
userContext = new HashMap<>();
@@ -188,6 +194,7 @@ public class Template implements Authorizable {
.action(action)
.resource(getResource())
.userContext(userContext)
+ .resourceContext(resourceContext)
.build();
// perform the authorization
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java
index 3745d7d..f77288a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java
@@ -139,6 +139,10 @@ public final class StandardConnection implements Connection {
@Override
public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
+ if (user == null) {
+ return AuthorizationResult.denied("Unknown user");
+ }
+
// check the source
final AuthorizationResult sourceResult = getSource().checkAuthorization(authorizer, action, user, resourceContext);
if (Result.Denied.equals(sourceResult.getResult())) {
@@ -151,6 +155,10 @@ public final class StandardConnection implements Connection {
@Override
public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
+ if (user == null) {
+ throw new AccessDeniedException("Unknown user");
+ }
+
getSource().authorize(authorizer, action, user, resourceContext);
getDestination().authorize(authorizer, action, user, resourceContext);
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
----------------------------------------------------------------------
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 30e382d..5de77f6 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
@@ -18,38 +18,6 @@ package org.apache.nifi.controller;
import com.sun.jersey.api.client.ClientHandlerException;
import org.apache.commons.collections4.Predicate;
-import static java.util.Objects.requireNonNull;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import javax.net.ssl.SSLContext;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.action.Action;
import org.apache.nifi.admin.service.AuditService;
@@ -63,7 +31,7 @@ import org.apache.nifi.authorization.Authorizer;
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.ProvenanceEventAuthorizable;
+import org.apache.nifi.authorization.resource.DataAuthorizable;
import org.apache.nifi.authorization.resource.ResourceFactory;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.cluster.HeartbeatPayload;
@@ -238,6 +206,37 @@ import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.net.ssl.SSLContext;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import static java.util.Objects.requireNonNull;
+
public class FlowController implements EventAccess, ControllerServiceProvider, ReportingTaskProvider, QueueProvider, Authorizable, ProvenanceAuthorizableFactory, NodeTypeProvider {
@@ -3902,15 +3901,15 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
}
@Override
- public Authorizable createProvenanceAuthorizable(final String componentId) {
+ public Authorizable createDataAuthorizable(final 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. So, we check if the component ID
// is set to the root group and otherwise assume that the ID is that of a component.
- final ProvenanceEventAuthorizable authorizable;
+ final DataAuthorizable authorizable;
if (rootGroupId.equals(componentId)) {
- authorizable = new ProvenanceEventAuthorizable(rootGroup);
+ authorizable = new DataAuthorizable(rootGroup);
} else {
final Connectable connectable = rootGroup.findConnectable(componentId);
@@ -3918,7 +3917,7 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
throw new ResourceNotFoundException("The component that generated this event is no longer part of the data flow.");
}
- authorizable = new ProvenanceEventAuthorizable(connectable);
+ authorizable = new DataAuthorizable(connectable);
}
return authorizable;
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
index e0faafb..bc958c3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
@@ -180,6 +180,13 @@ public interface AuthorizableLookup {
Authorizable getTenant();
/**
+ * Get the authorizable for data of a specified component.
+ *
+ * @return authorizable
+ */
+ Authorizable getData(String id);
+
+ /**
* Get the authorizable for access all policies.
*
* @return authorizable
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
----------------------------------------------------------------------
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 c0805c0..1e3c03a 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
@@ -20,7 +20,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.authorization.resource.AccessPolicyAuthorizable;
import org.apache.nifi.authorization.resource.Authorizable;
import org.apache.nifi.authorization.resource.DataTransferAuthorizable;
-import org.apache.nifi.authorization.resource.ProvenanceEventAuthorizable;
+import org.apache.nifi.authorization.resource.DataAuthorizable;
import org.apache.nifi.authorization.resource.ResourceFactory;
import org.apache.nifi.authorization.resource.ResourceType;
import org.apache.nifi.authorization.resource.TenantAuthorizable;
@@ -234,6 +234,11 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
}
@Override
+ public Authorizable getData(final String id) {
+ return controllerFacade.getDataAuthorizable(id);
+ }
+
+ @Override
public Authorizable getPolicies() {
return POLICIES_AUTHORIZABLE;
}
@@ -269,7 +274,7 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
}
// if this is a policy or a provenance event resource, there should be another resource type
- if (ResourceType.Policy.equals(resourceType) || ResourceType.ProvenanceEvent.equals(resourceType) || ResourceType.DataTransfer.equals(resourceType)) {
+ if (ResourceType.Policy.equals(resourceType) || ResourceType.Data.equals(resourceType) || ResourceType.DataTransfer.equals(resourceType)) {
final ResourceType primaryResourceType = resourceType;
// get the resource type
@@ -288,8 +293,8 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
// must either be a policy, event, or data transfer
if (ResourceType.Policy.equals(primaryResourceType)) {
return new AccessPolicyAuthorizable(getAccessPolicy(resourceType, resource));
- } else if (ResourceType.ProvenanceEvent.equals(primaryResourceType)) {
- return new ProvenanceEventAuthorizable(getAccessPolicy(resourceType, resource));
+ } else if (ResourceType.Data.equals(primaryResourceType)) {
+ return new DataAuthorizable(getAccessPolicy(resourceType, resource));
} else {
return new DataTransferAuthorizable(getAccessPolicy(resourceType, resource));
}
@@ -340,8 +345,8 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
case Template:
authorizable = getTemplate(componentId);
break;
- case ProvenanceEvent:
- authorizable = controllerFacade.getProvenanceEventAuthorizable(componentId);
+ case Data:
+ authorizable = controllerFacade.getDataAuthorizable(componentId);
break;
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
index 1786bce..e17b147 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
@@ -164,20 +164,12 @@ public class StandardNiFiContentAccess implements ContentAccess {
}
private DownloadableContent getFlowFileContent(final String connectionId, final String flowfileId, final String dataUri) {
- // TODO - ensure the user is authorized - not checking with @PreAuthorized annotation as aspect not trigger on call within a class
-// if (!NiFiUserUtils.getAuthorities().contains(Authority.ROLE_DFM.toString())) {
-// throw new AccessDeniedException("Access is denied.");
-// }
-
+ // user authorization is handled once we have the actual content so we can utilize the flow file attributes in the resource context
return serviceFacade.getContent(connectionId, flowfileId, dataUri);
}
private DownloadableContent getProvenanceEventContent(final Long eventId, final String dataUri, final ContentDirection direction) {
- // TODO - ensure the user is authorized - not checking with @PreAuthorized annotation as aspect not trigger on call within a class
-// if (!NiFiUserUtils.getAuthorities().contains(Authority.ROLE_PROVENANCE.toString())) {
-// throw new AccessDeniedException("Access is denied.");
-// }
-
+ // user authorization is handled once we have the actual prov event so we can utilize the event attributes in the resource context
return serviceFacade.getContent(eventId, dataUri, direction);
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
----------------------------------------------------------------------
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 6186bf1..b2b93db 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
@@ -37,6 +37,7 @@ import org.apache.nifi.authorization.Resource;
import org.apache.nifi.authorization.User;
import org.apache.nifi.authorization.resource.Authorizable;
import org.apache.nifi.authorization.resource.DataTransferAuthorizable;
+import org.apache.nifi.authorization.resource.ResourceFactory;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserUtils;
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
@@ -850,8 +851,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final Connection connection = connectionDAO.getConnection(connectionId);
final ConnectionDTO snapshot = deleteComponent(
revision,
- connection,
+ connection.getResource().getIdentifier(),
() -> connectionDAO.deleteConnection(connectionId),
+ false,
dtoFactory.createConnectionDto(connection));
return entityFactory.createConnectionEntity(snapshot, null, null, null);
@@ -883,8 +885,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final ProcessorNode processor = processorDAO.getProcessor(processorId);
final ProcessorDTO snapshot = deleteComponent(
revision,
- processor,
+ processor.getResource().getIdentifier(),
() -> processorDAO.deleteProcessor(processorId),
+ true,
dtoFactory.createProcessorDto(processor));
return entityFactory.createProcessorEntity(snapshot, null, null, null, null);
@@ -895,8 +898,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final Label label = labelDAO.getLabel(labelId);
final LabelDTO snapshot = deleteComponent(
revision,
- label,
+ label.getResource().getIdentifier(),
() -> labelDAO.deleteLabel(labelId),
+ true,
dtoFactory.createLabelDto(label));
return entityFactory.createLabelEntity(snapshot, null, null);
@@ -910,21 +914,13 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final Set<AccessPolicySummaryEntity> policyEntities = user != null ? userGroupDAO.getAccessPoliciesForUser(userId).stream()
.map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()) : null;
- final RevisionClaim claim = new StandardRevisionClaim(revision);
- final NiFiUser nifiUser = NiFiUserUtils.getNiFiUser();
-
- // perform the deletion
- final UserDTO snapshot = revisionManager.deleteRevision(claim, nifiUser, () -> {
- logger.debug("Attempting to delete component {} with claim {}", user, claim);
-
- userDAO.deleteUser(userId);
-
- // save the flow
- controllerFacade.save();
- logger.debug("Deletion of component {} was successful", user);
-
- return dtoFactory.createUserDto(user, userGroups, policyEntities);
- });
+ final String resourceIdentifier = ResourceFactory.getTenantResource().getIdentifier() + "/" + userId;
+ final UserDTO snapshot = deleteComponent(
+ revision,
+ resourceIdentifier,
+ () -> userDAO.deleteUser(userId),
+ false, // no user specific policies to remove
+ dtoFactory.createUserDto(user, userGroups, policyEntities));
return entityFactory.createUserEntity(snapshot, null, null);
}
@@ -936,21 +932,13 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
.map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) :
null;
- final RevisionClaim claim = new StandardRevisionClaim(revision);
- final NiFiUser nifiUser = NiFiUserUtils.getNiFiUser();
-
- // perform the deletion
- final UserGroupDTO snapshot = revisionManager.deleteRevision(claim, nifiUser, () -> {
- logger.debug("Attempting to delete component {} with claim {}", userGroup, claim);
-
- userGroupDAO.deleteUserGroup(userGroupId);
-
- // save the flow
- controllerFacade.save();
- logger.debug("Deletion of component {} was successful", userGroup);
-
- return dtoFactory.createUserGroupDto(userGroup, users);
- });
+ final String resourceIdentifier = ResourceFactory.getTenantResource().getIdentifier() + "/" + userGroupId;
+ final UserGroupDTO snapshot = deleteComponent(
+ revision,
+ resourceIdentifier,
+ () -> userGroupDAO.deleteUserGroup(userGroupId),
+ false, // no user group specific policies to remove
+ dtoFactory.createUserGroupDto(userGroup, users));
return entityFactory.createUserGroupEntity(snapshot, null, null);
}
@@ -962,8 +950,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final Set<TenantEntity> users = accessPolicy != null ? accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) : null;
final AccessPolicyDTO snapshot = deleteComponent(
revision,
- authorizableLookup.getAccessPolicyById(accessPolicyId),
+ accessPolicy.getResource(),
() -> accessPolicyDAO.deleteAccessPolicy(accessPolicyId),
+ false, // no need to clean up any policies as it's already been removed above
dtoFactory.createAccessPolicyDto(accessPolicy, userGroups,
users));
@@ -975,8 +964,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final Funnel funnel = funnelDAO.getFunnel(funnelId);
final FunnelDTO snapshot = deleteComponent(
revision,
- funnel,
+ funnel.getResource().getIdentifier(),
() -> funnelDAO.deleteFunnel(funnelId),
+ true,
dtoFactory.createFunnelDto(funnel));
return entityFactory.createFunnelEntity(snapshot, null, null);
@@ -986,47 +976,49 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
* Deletes a component using the Optimistic Locking Manager
*
* @param revision the current revision
+ * @param resourceIdentifier the identifier of the resource being removed
* @param deleteAction the action that deletes the component via the appropriate DAO object
+ * @param cleanUpPolicies whether or not the policies for this resource should be removed as well - not necessary when there are
+ * no component specific policies or if the policies of the component are inherited
* @return a dto that represents the new configuration
*/
- private <D, C> D deleteComponent(final Revision revision, final Authorizable authorizable, final Runnable deleteAction, final D dto) {
+ private <D, C> D deleteComponent(final Revision revision, final String resourceIdentifier, final Runnable deleteAction, final boolean cleanUpPolicies, final D dto) {
final RevisionClaim claim = new StandardRevisionClaim(revision);
final NiFiUser user = NiFiUserUtils.getNiFiUser();
return revisionManager.deleteRevision(claim, user, new DeleteRevisionTask<D>() {
@Override
public D performTask() {
- logger.debug("Attempting to delete component {} with claim {}", authorizable, claim);
+ logger.debug("Attempting to delete component {} with claim {}", resourceIdentifier, claim);
+ // run the delete action
deleteAction.run();
// save the flow
controllerFacade.save();
- logger.debug("Deletion of component {} was successful", authorizable);
+ logger.debug("Deletion of component {} was successful", resourceIdentifier);
- // if configured with a policy based authorizer, attempt to remove the corresponding policies
- if (authorizer instanceof AbstractPolicyBasedAuthorizer) {
+ // clean up the policy if necessary and configured with a policy based authorizer
+ if (cleanUpPolicies && authorizer instanceof AbstractPolicyBasedAuthorizer) {
try {
// since the component is being deleted, also delete any relevant read access policies
- final AccessPolicy readPolicy = accessPolicyDAO.getAccessPolicy(RequestAction.READ, authorizable);
- if (authorizable.getResource().getIdentifier().equals(readPolicy.getResource())) {
+ final AccessPolicy readPolicy = accessPolicyDAO.getAccessPolicy(RequestAction.READ, resourceIdentifier);
+ if (readPolicy != null) {
accessPolicyDAO.deleteAccessPolicy(readPolicy.getIdentifier());
}
- } catch (final ResourceNotFoundException e) {
- // no policy exists for this component... no worries
} catch (final Exception e) {
- logger.warn(String.format("Unable to remove access policy for %s %s after component removal.", RequestAction.READ, authorizable.getResource().getIdentifier()), e);
+ logger.warn(String.format("Unable to remove access policy for %s %s after component removal.", RequestAction.READ, resourceIdentifier), e);
}
try {
// since the component is being deleted, also delete any relevant write access policies
- final AccessPolicy writePolicy = accessPolicyDAO.getAccessPolicy(RequestAction.WRITE, authorizable);
- if (authorizable.getResource().getIdentifier().equals(writePolicy.getResource())) {
+ final AccessPolicy writePolicy = accessPolicyDAO.getAccessPolicy(RequestAction.WRITE, resourceIdentifier);
+ if (writePolicy != null) {
accessPolicyDAO.deleteAccessPolicy(writePolicy.getIdentifier());
}
} catch (final ResourceNotFoundException e) {
// no policy exists for this component... no worries
} catch (final Exception e) {
- logger.warn(String.format("Unable to remove access policy for %s %s after component removal.", RequestAction.WRITE, authorizable.getResource().getIdentifier()), e);
+ logger.warn(String.format("Unable to remove access policy for %s %s after component removal.", RequestAction.WRITE, resourceIdentifier), e);
}
}
@@ -1071,8 +1063,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final Port port = inputPortDAO.getPort(inputPortId);
final PortDTO snapshot = deleteComponent(
revision,
- port,
+ port.getResource().getIdentifier(),
() -> inputPortDAO.deletePort(inputPortId),
+ true,
dtoFactory.createPortDto(port));
return entityFactory.createPortEntity(snapshot, null, null, null, null);
@@ -1083,8 +1076,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final Port port = outputPortDAO.getPort(outputPortId);
final PortDTO snapshot = deleteComponent(
revision,
- port,
+ port.getResource().getIdentifier(),
() -> outputPortDAO.deletePort(outputPortId),
+ true,
dtoFactory.createPortDto(port));
return entityFactory.createPortEntity(snapshot, null, null, null, null);
@@ -1095,8 +1089,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
final ProcessGroupDTO snapshot = deleteComponent(
revision,
- processGroup,
+ processGroup.getResource().getIdentifier(),
() -> processGroupDAO.deleteProcessGroup(groupId),
+ true,
dtoFactory.createProcessGroupDto(processGroup));
return entityFactory.createProcessGroupEntity(snapshot, null, null, null, null);
@@ -1107,8 +1102,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final RemoteProcessGroup remoteProcessGroup = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupId);
final RemoteProcessGroupDTO snapshot = deleteComponent(
revision,
- remoteProcessGroup,
+ remoteProcessGroup.getResource().getIdentifier(),
() -> remoteProcessGroupDAO.deleteRemoteProcessGroup(remoteProcessGroupId),
+ true,
dtoFactory.createRemoteProcessGroupDto(remoteProcessGroup));
return entityFactory.createRemoteProcessGroupEntity(snapshot, null, null, null, null);
@@ -1740,8 +1736,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final ControllerServiceNode controllerService = controllerServiceDAO.getControllerService(controllerServiceId);
final ControllerServiceDTO snapshot = deleteComponent(
revision,
- controllerService,
+ controllerService.getResource().getIdentifier(),
() -> controllerServiceDAO.deleteControllerService(controllerServiceId),
+ true,
dtoFactory.createControllerServiceDto(controllerService));
return entityFactory.createControllerServiceEntity(snapshot, null, null, null);
@@ -1793,8 +1790,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final ReportingTaskNode reportingTask = reportingTaskDAO.getReportingTask(reportingTaskId);
final ReportingTaskDTO snapshot = deleteComponent(
revision,
- reportingTask,
+ reportingTask.getResource().getIdentifier(),
() -> reportingTaskDAO.deleteReportingTask(reportingTaskId),
+ true,
dtoFactory.createReportingTaskDto(reportingTask));
return entityFactory.createReportingTaskEntity(snapshot, null, null, null);
http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java
index c77ed65..8a03dbf 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java
@@ -83,9 +83,7 @@ public class AccessPolicyResource extends ApplicationResource {
* @return accessPolicyEntity
*/
public AccessPolicyEntity populateRemainingAccessPolicyEntityContent(AccessPolicyEntity accessPolicyEntity) {
- if (accessPolicyEntity.getComponent() != null) {
- accessPolicyEntity.setUri(generateResourceUri("policies", accessPolicyEntity.getId()));
- }
+ accessPolicyEntity.setUri(generateResourceUri("policies", accessPolicyEntity.getId()));
return accessPolicyEntity;
}
@@ -229,7 +227,7 @@ public class AccessPolicyResource extends ApplicationResource {
}
// set the access policy id as appropriate
- accessPolicyEntity.getComponent().setId(generateUuid());
+ requestAccessPolicy.setId(generateUuid());
// get revision from the config
final RevisionDTO revisionDTO = accessPolicyEntity.getRevision();
@@ -286,7 +284,7 @@ public class AccessPolicyResource extends ApplicationResource {
// authorize access
serviceFacade.authorizeAccess(lookup -> {
Authorizable authorizable = lookup.getAccessPolicyById(id);
- authorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+ authorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
});
// get the access policy
@@ -438,7 +436,7 @@ public class AccessPolicyResource extends ApplicationResource {
revision,
lookup -> {
final Authorizable accessPolicy = lookup.getAccessPolicyById(id);
- accessPolicy.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
+ accessPolicy.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
},
() -> {
},