mirror of https://github.com/apache/nifi.git
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.
This commit is contained in:
parent
c27763a12f
commit
69586d8bd0
|
@ -69,6 +69,10 @@ public interface Authorizable {
|
||||||
* @return is authorized
|
* @return is authorized
|
||||||
*/
|
*/
|
||||||
default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
|
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;
|
final Map<String,String> userContext;
|
||||||
if (user.getClientAddress() != null && !user.getClientAddress().trim().isEmpty()) {
|
if (user.getClientAddress() != null && !user.getClientAddress().trim().isEmpty()) {
|
||||||
userContext = new HashMap<>();
|
userContext = new HashMap<>();
|
||||||
|
@ -128,6 +132,10 @@ public interface Authorizable {
|
||||||
* @param resourceContext resource context
|
* @param resourceContext resource context
|
||||||
*/
|
*/
|
||||||
default void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
|
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;
|
final Map<String,String> userContext;
|
||||||
if (user.getClientAddress() != null && !user.getClientAddress().trim().isEmpty()) {
|
if (user.getClientAddress() != null && !user.getClientAddress().trim().isEmpty()) {
|
||||||
userContext = new HashMap<>();
|
userContext = new HashMap<>();
|
||||||
|
|
|
@ -23,13 +23,14 @@ import org.apache.nifi.web.ResourceNotFoundException;
|
||||||
public interface ProvenanceAuthorizableFactory {
|
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
|
* @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
|
* @throws ResourceNotFoundException if no component can be found with the given ID
|
||||||
*/
|
*/
|
||||||
Authorizable createProvenanceAuthorizable(String componentId);
|
Authorizable createDataAuthorizable(String componentId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,6 +276,9 @@ public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
|
||||||
|
|
||||||
// grant the user read access to the root process group resource
|
// grant the user read access to the root process group resource
|
||||||
if (rootGroupId != null) {
|
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(), READ_CODE);
|
||||||
addAccessPolicy(authorizations, ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), WRITE_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
|
// grant access to the proxy resource
|
||||||
addAccessPolicy(authorizations, ResourceType.Proxy.getValue(), jaxbNodeUser.getIdentifier(), READ_CODE);
|
addAccessPolicy(authorizations, ResourceType.Proxy.getValue(), jaxbNodeUser.getIdentifier(), READ_CODE);
|
||||||
addAccessPolicy(authorizations, ResourceType.Proxy.getValue(), jaxbNodeUser.getIdentifier(), WRITE_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ public final class RoleAccessPolicy {
|
||||||
final Set<RoleAccessPolicy> provenancePolicies = new HashSet<>();
|
final Set<RoleAccessPolicy> provenancePolicies = new HashSet<>();
|
||||||
provenancePolicies.add(new RoleAccessPolicy(ResourceType.Provenance.getValue(), READ_ACTION));
|
provenancePolicies.add(new RoleAccessPolicy(ResourceType.Provenance.getValue(), READ_ACTION));
|
||||||
if (rootGroupId != null) {
|
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));
|
roleAccessPolicies.put(Role.ROLE_PROVENANCE, Collections.unmodifiableSet(provenancePolicies));
|
||||||
|
|
||||||
|
@ -75,6 +75,8 @@ public final class RoleAccessPolicy {
|
||||||
if (rootGroupId != null) {
|
if (rootGroupId != null) {
|
||||||
dfmPolicies.add(new RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
|
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.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));
|
roleAccessPolicies.put(Role.ROLE_DFM, Collections.unmodifiableSet(dfmPolicies));
|
||||||
|
|
||||||
|
@ -93,6 +95,10 @@ public final class RoleAccessPolicy {
|
||||||
final Set<RoleAccessPolicy> proxyPolicies = new HashSet<>();
|
final Set<RoleAccessPolicy> proxyPolicies = new HashSet<>();
|
||||||
proxyPolicies.add(new RoleAccessPolicy(ResourceType.Proxy.getValue(), READ_ACTION));
|
proxyPolicies.add(new RoleAccessPolicy(ResourceType.Proxy.getValue(), READ_ACTION));
|
||||||
proxyPolicies.add(new RoleAccessPolicy(ResourceType.Proxy.getValue(), WRITE_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));
|
roleAccessPolicies.put(Role.ROLE_PROXY, Collections.unmodifiableSet(proxyPolicies));
|
||||||
|
|
||||||
final Set<RoleAccessPolicy> nifiPolicies = new HashSet<>();
|
final Set<RoleAccessPolicy> nifiPolicies = new HashSet<>();
|
||||||
|
|
|
@ -254,7 +254,7 @@ public class FileAuthorizerTest {
|
||||||
|
|
||||||
// verify user3's policies
|
// verify user3's policies
|
||||||
final Map<String,Set<RequestAction>> user3Policies = getResourceActions(policies, user3);
|
final Map<String,Set<RequestAction>> user3Policies = getResourceActions(policies, user3);
|
||||||
assertEquals(4, user3Policies.size());
|
assertEquals(5, user3Policies.size());
|
||||||
|
|
||||||
assertTrue(user3Policies.containsKey(ResourceType.Flow.getValue()));
|
assertTrue(user3Policies.containsKey(ResourceType.Flow.getValue()));
|
||||||
assertEquals(1, user3Policies.get(ResourceType.Flow.getValue()).size());
|
assertEquals(1, user3Policies.get(ResourceType.Flow.getValue()).size());
|
||||||
|
@ -286,7 +286,7 @@ public class FileAuthorizerTest {
|
||||||
|
|
||||||
// verify user5's policies
|
// verify user5's policies
|
||||||
final Map<String,Set<RequestAction>> user5Policies = getResourceActions(policies, user5);
|
final Map<String,Set<RequestAction>> user5Policies = getResourceActions(policies, user5);
|
||||||
assertEquals(1, user5Policies.size());
|
assertEquals(2, user5Policies.size());
|
||||||
|
|
||||||
assertTrue(user5Policies.containsKey(ResourceType.Proxy.getValue()));
|
assertTrue(user5Policies.containsKey(ResourceType.Proxy.getValue()));
|
||||||
assertEquals(2, user5Policies.get(ResourceType.Proxy.getValue()).size());
|
assertEquals(2, user5Policies.get(ResourceType.Proxy.getValue()).size());
|
||||||
|
@ -384,7 +384,7 @@ public class FileAuthorizerTest {
|
||||||
assertEquals(adminIdentity, adminUser.getIdentity());
|
assertEquals(adminIdentity, adminUser.getIdentity());
|
||||||
|
|
||||||
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
||||||
assertEquals(9, policies.size());
|
assertEquals(11, policies.size());
|
||||||
|
|
||||||
final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
|
final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,33 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.authorization.resource;
|
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.Resource;
|
||||||
|
import org.apache.nifi.authorization.user.NiFiUser;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authorizable for policies of an Authorizable.
|
* 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;
|
final Authorizable authorizable;
|
||||||
|
|
||||||
public AccessPolicyAuthorizable(Authorizable authorizable) {
|
public AccessPolicyAuthorizable(Authorizable authorizable) {
|
||||||
|
@ -29,26 +50,73 @@ public class AccessPolicyAuthorizable implements Authorizable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authorizable getParentAuthorizable() {
|
public Authorizable getBaseAuthorizable() {
|
||||||
if (authorizable.getParentAuthorizable() == null) {
|
return authorizable;
|
||||||
return new Authorizable() {
|
}
|
||||||
@Override
|
|
||||||
public Authorizable getParentAuthorizable() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Resource getResource() {
|
public Authorizable getParentAuthorizable() {
|
||||||
return ResourceFactory.getPoliciesResource();
|
final Authorizable effectiveAuthorizable = getEffectiveAuthorizable();
|
||||||
}
|
if (effectiveAuthorizable.getParentAuthorizable() == null) {
|
||||||
};
|
return POLICIES_AUTHORIZABLE;
|
||||||
} else {
|
} else {
|
||||||
return new AccessPolicyAuthorizable(authorizable.getParentAuthorizable());
|
return new AccessPolicyAuthorizable(effectiveAuthorizable.getParentAuthorizable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Resource getResource() {
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,12 +19,13 @@ package org.apache.nifi.authorization.resource;
|
||||||
import 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;
|
final Authorizable authorizable;
|
||||||
|
|
||||||
public DataTransferAuthorizable(Authorizable authorizable) {
|
public DataTransferAuthorizable(Authorizable authorizable) {
|
||||||
|
super(authorizable);
|
||||||
this.authorizable = authorizable;
|
this.authorizable = authorizable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
@Override
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
return ResourceType.ProvenanceEvent.getValue();
|
return ResourceType.Data.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
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
|
* @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 provenance of the component being accessed
|
||||||
*/
|
*/
|
||||||
public static Resource getProvenanceEventResource(final Resource resource) {
|
public static Resource getDataResource(final Resource resource) {
|
||||||
return new Resource() {
|
return new Resource() {
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifier() {
|
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
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Provenance Events for " + resource.getName();
|
return "Data for " + resource.getName();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ public enum ResourceType {
|
||||||
Processor("/processors"),
|
Processor("/processors"),
|
||||||
ProcessGroup("/process-groups"),
|
ProcessGroup("/process-groups"),
|
||||||
Provenance("/provenance"),
|
Provenance("/provenance"),
|
||||||
ProvenanceEvent("/provenance-events"),
|
Data("/data"),
|
||||||
Proxy("/proxy"),
|
Proxy("/proxy"),
|
||||||
RemoteProcessGroup("/remote-process-groups"),
|
RemoteProcessGroup("/remote-process-groups"),
|
||||||
ReportingTask("/reporting-tasks"),
|
ReportingTask("/reporting-tasks"),
|
||||||
|
|
|
@ -20,6 +20,9 @@ import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
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.
|
* Utility methods for retrieving information about the current application user.
|
||||||
*
|
*
|
||||||
|
@ -56,4 +59,27 @@ public final class NiFiUserUtils {
|
||||||
return user.getIdentity();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,20 +158,26 @@ public class Template implements Authorizable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authorize(final Authorizer authorizer, final RequestAction action, final NiFiUser user) throws AccessDeniedException {
|
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);
|
final AuthorizationResult result = checkAuthorization(authorizer, action, true, user, resourceContext);
|
||||||
if (Result.Denied.equals(result)) {
|
if (Result.Denied.equals(result.getResult())) {
|
||||||
final String explanation = result.getExplanation() == null ? "Access is denied" : result.getExplanation();
|
final String explanation = result.getExplanation() == null ? "Access is denied" : result.getExplanation();
|
||||||
throw new AccessDeniedException(explanation);
|
throw new AccessDeniedException(explanation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final NiFiUser user) {
|
public AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final NiFiUser user, final Map<String, String> resourceContext) {
|
||||||
return checkAuthorization(authorizer, action, false, user);
|
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;
|
final Map<String,String> userContext;
|
||||||
if (!StringUtils.isBlank(user.getClientAddress())) {
|
if (!StringUtils.isBlank(user.getClientAddress())) {
|
||||||
userContext = new HashMap<>();
|
userContext = new HashMap<>();
|
||||||
|
@ -188,6 +194,7 @@ public class Template implements Authorizable {
|
||||||
.action(action)
|
.action(action)
|
||||||
.resource(getResource())
|
.resource(getResource())
|
||||||
.userContext(userContext)
|
.userContext(userContext)
|
||||||
|
.resourceContext(resourceContext)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// perform the authorization
|
// perform the authorization
|
||||||
|
|
|
@ -139,6 +139,10 @@ public final class StandardConnection implements Connection {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
|
public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
|
||||||
|
if (user == null) {
|
||||||
|
return AuthorizationResult.denied("Unknown user");
|
||||||
|
}
|
||||||
|
|
||||||
// check the source
|
// check the source
|
||||||
final AuthorizationResult sourceResult = getSource().checkAuthorization(authorizer, action, user, resourceContext);
|
final AuthorizationResult sourceResult = getSource().checkAuthorization(authorizer, action, user, resourceContext);
|
||||||
if (Result.Denied.equals(sourceResult.getResult())) {
|
if (Result.Denied.equals(sourceResult.getResult())) {
|
||||||
|
@ -151,6 +155,10 @@ public final class StandardConnection implements Connection {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
|
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);
|
getSource().authorize(authorizer, action, user, resourceContext);
|
||||||
getDestination().authorize(authorizer, action, user, resourceContext);
|
getDestination().authorize(authorizer, action, user, resourceContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,38 +18,6 @@ package org.apache.nifi.controller;
|
||||||
|
|
||||||
import com.sun.jersey.api.client.ClientHandlerException;
|
import com.sun.jersey.api.client.ClientHandlerException;
|
||||||
import org.apache.commons.collections4.Predicate;
|
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.commons.lang3.StringUtils;
|
||||||
import org.apache.nifi.action.Action;
|
import org.apache.nifi.action.Action;
|
||||||
import org.apache.nifi.admin.service.AuditService;
|
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.RequestAction;
|
||||||
import org.apache.nifi.authorization.Resource;
|
import org.apache.nifi.authorization.Resource;
|
||||||
import org.apache.nifi.authorization.resource.Authorizable;
|
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.resource.ResourceFactory;
|
||||||
import org.apache.nifi.authorization.user.NiFiUser;
|
import org.apache.nifi.authorization.user.NiFiUser;
|
||||||
import org.apache.nifi.cluster.HeartbeatPayload;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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 {
|
public class FlowController implements EventAccess, ControllerServiceProvider, ReportingTaskProvider, QueueProvider, Authorizable, ProvenanceAuthorizableFactory, NodeTypeProvider {
|
||||||
|
|
||||||
|
@ -3902,15 +3901,15 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authorizable createProvenanceAuthorizable(final String componentId) {
|
public Authorizable createDataAuthorizable(final String componentId) {
|
||||||
final String rootGroupId = getRootGroupId();
|
final String rootGroupId = getRootGroupId();
|
||||||
|
|
||||||
// Provenance Events are generated only by connectable components, with the exception of DOWNLOAD events,
|
// 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
|
// 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.
|
// 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)) {
|
if (rootGroupId.equals(componentId)) {
|
||||||
authorizable = new ProvenanceEventAuthorizable(rootGroup);
|
authorizable = new DataAuthorizable(rootGroup);
|
||||||
} else {
|
} else {
|
||||||
final Connectable connectable = rootGroup.findConnectable(componentId);
|
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.");
|
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;
|
return authorizable;
|
||||||
|
|
|
@ -179,6 +179,13 @@ public interface AuthorizableLookup {
|
||||||
*/
|
*/
|
||||||
Authorizable getTenant();
|
Authorizable getTenant();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the authorizable for data of a specified component.
|
||||||
|
*
|
||||||
|
* @return authorizable
|
||||||
|
*/
|
||||||
|
Authorizable getData(String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the authorizable for access all policies.
|
* Get the authorizable for access all policies.
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,7 +20,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.nifi.authorization.resource.AccessPolicyAuthorizable;
|
import org.apache.nifi.authorization.resource.AccessPolicyAuthorizable;
|
||||||
import org.apache.nifi.authorization.resource.Authorizable;
|
import org.apache.nifi.authorization.resource.Authorizable;
|
||||||
import org.apache.nifi.authorization.resource.DataTransferAuthorizable;
|
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.ResourceFactory;
|
||||||
import org.apache.nifi.authorization.resource.ResourceType;
|
import org.apache.nifi.authorization.resource.ResourceType;
|
||||||
import org.apache.nifi.authorization.resource.TenantAuthorizable;
|
import org.apache.nifi.authorization.resource.TenantAuthorizable;
|
||||||
|
@ -233,6 +233,11 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
|
||||||
return TENANT_AUTHORIZABLE;
|
return TENANT_AUTHORIZABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authorizable getData(final String id) {
|
||||||
|
return controllerFacade.getDataAuthorizable(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authorizable getPolicies() {
|
public Authorizable getPolicies() {
|
||||||
return POLICIES_AUTHORIZABLE;
|
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 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;
|
final ResourceType primaryResourceType = resourceType;
|
||||||
|
|
||||||
// get the resource type
|
// get the resource type
|
||||||
|
@ -288,8 +293,8 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
|
||||||
// must either be a policy, event, or data transfer
|
// must either be a policy, event, or data transfer
|
||||||
if (ResourceType.Policy.equals(primaryResourceType)) {
|
if (ResourceType.Policy.equals(primaryResourceType)) {
|
||||||
return new AccessPolicyAuthorizable(getAccessPolicy(resourceType, resource));
|
return new AccessPolicyAuthorizable(getAccessPolicy(resourceType, resource));
|
||||||
} else if (ResourceType.ProvenanceEvent.equals(primaryResourceType)) {
|
} else if (ResourceType.Data.equals(primaryResourceType)) {
|
||||||
return new ProvenanceEventAuthorizable(getAccessPolicy(resourceType, resource));
|
return new DataAuthorizable(getAccessPolicy(resourceType, resource));
|
||||||
} else {
|
} else {
|
||||||
return new DataTransferAuthorizable(getAccessPolicy(resourceType, resource));
|
return new DataTransferAuthorizable(getAccessPolicy(resourceType, resource));
|
||||||
}
|
}
|
||||||
|
@ -340,8 +345,8 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
|
||||||
case Template:
|
case Template:
|
||||||
authorizable = getTemplate(componentId);
|
authorizable = getTemplate(componentId);
|
||||||
break;
|
break;
|
||||||
case ProvenanceEvent:
|
case Data:
|
||||||
authorizable = controllerFacade.getProvenanceEventAuthorizable(componentId);
|
authorizable = controllerFacade.getDataAuthorizable(componentId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,20 +164,12 @@ public class StandardNiFiContentAccess implements ContentAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DownloadableContent getFlowFileContent(final String connectionId, final String flowfileId, final String dataUri) {
|
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
|
// user authorization is handled once we have the actual content so we can utilize the flow file attributes in the resource context
|
||||||
// if (!NiFiUserUtils.getAuthorities().contains(Authority.ROLE_DFM.toString())) {
|
|
||||||
// throw new AccessDeniedException("Access is denied.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
return serviceFacade.getContent(connectionId, flowfileId, dataUri);
|
return serviceFacade.getContent(connectionId, flowfileId, dataUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DownloadableContent getProvenanceEventContent(final Long eventId, final String dataUri, final ContentDirection direction) {
|
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
|
// user authorization is handled once we have the actual prov event so we can utilize the event attributes in the resource context
|
||||||
// if (!NiFiUserUtils.getAuthorities().contains(Authority.ROLE_PROVENANCE.toString())) {
|
|
||||||
// throw new AccessDeniedException("Access is denied.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
return serviceFacade.getContent(eventId, dataUri, direction);
|
return serviceFacade.getContent(eventId, dataUri, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.nifi.authorization.Resource;
|
||||||
import org.apache.nifi.authorization.User;
|
import org.apache.nifi.authorization.User;
|
||||||
import org.apache.nifi.authorization.resource.Authorizable;
|
import org.apache.nifi.authorization.resource.Authorizable;
|
||||||
import org.apache.nifi.authorization.resource.DataTransferAuthorizable;
|
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.NiFiUser;
|
||||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||||
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
|
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
|
||||||
|
@ -850,8 +851,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final Connection connection = connectionDAO.getConnection(connectionId);
|
final Connection connection = connectionDAO.getConnection(connectionId);
|
||||||
final ConnectionDTO snapshot = deleteComponent(
|
final ConnectionDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
connection,
|
connection.getResource().getIdentifier(),
|
||||||
() -> connectionDAO.deleteConnection(connectionId),
|
() -> connectionDAO.deleteConnection(connectionId),
|
||||||
|
false,
|
||||||
dtoFactory.createConnectionDto(connection));
|
dtoFactory.createConnectionDto(connection));
|
||||||
|
|
||||||
return entityFactory.createConnectionEntity(snapshot, null, null, null);
|
return entityFactory.createConnectionEntity(snapshot, null, null, null);
|
||||||
|
@ -883,8 +885,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final ProcessorNode processor = processorDAO.getProcessor(processorId);
|
final ProcessorNode processor = processorDAO.getProcessor(processorId);
|
||||||
final ProcessorDTO snapshot = deleteComponent(
|
final ProcessorDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
processor,
|
processor.getResource().getIdentifier(),
|
||||||
() -> processorDAO.deleteProcessor(processorId),
|
() -> processorDAO.deleteProcessor(processorId),
|
||||||
|
true,
|
||||||
dtoFactory.createProcessorDto(processor));
|
dtoFactory.createProcessorDto(processor));
|
||||||
|
|
||||||
return entityFactory.createProcessorEntity(snapshot, null, null, null, null);
|
return entityFactory.createProcessorEntity(snapshot, null, null, null, null);
|
||||||
|
@ -895,8 +898,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final Label label = labelDAO.getLabel(labelId);
|
final Label label = labelDAO.getLabel(labelId);
|
||||||
final LabelDTO snapshot = deleteComponent(
|
final LabelDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
label,
|
label.getResource().getIdentifier(),
|
||||||
() -> labelDAO.deleteLabel(labelId),
|
() -> labelDAO.deleteLabel(labelId),
|
||||||
|
true,
|
||||||
dtoFactory.createLabelDto(label));
|
dtoFactory.createLabelDto(label));
|
||||||
|
|
||||||
return entityFactory.createLabelEntity(snapshot, null, null);
|
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()
|
final Set<AccessPolicySummaryEntity> policyEntities = user != null ? userGroupDAO.getAccessPoliciesForUser(userId).stream()
|
||||||
.map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()) : null;
|
.map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()) : null;
|
||||||
|
|
||||||
final RevisionClaim claim = new StandardRevisionClaim(revision);
|
final String resourceIdentifier = ResourceFactory.getTenantResource().getIdentifier() + "/" + userId;
|
||||||
final NiFiUser nifiUser = NiFiUserUtils.getNiFiUser();
|
final UserDTO snapshot = deleteComponent(
|
||||||
|
revision,
|
||||||
// perform the deletion
|
resourceIdentifier,
|
||||||
final UserDTO snapshot = revisionManager.deleteRevision(claim, nifiUser, () -> {
|
() -> userDAO.deleteUser(userId),
|
||||||
logger.debug("Attempting to delete component {} with claim {}", user, claim);
|
false, // no user specific policies to remove
|
||||||
|
dtoFactory.createUserDto(user, userGroups, policyEntities));
|
||||||
userDAO.deleteUser(userId);
|
|
||||||
|
|
||||||
// save the flow
|
|
||||||
controllerFacade.save();
|
|
||||||
logger.debug("Deletion of component {} was successful", user);
|
|
||||||
|
|
||||||
return dtoFactory.createUserDto(user, userGroups, policyEntities);
|
|
||||||
});
|
|
||||||
|
|
||||||
return entityFactory.createUserEntity(snapshot, null, null);
|
return entityFactory.createUserEntity(snapshot, null, null);
|
||||||
}
|
}
|
||||||
|
@ -936,21 +932,13 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
.map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) :
|
.map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
final RevisionClaim claim = new StandardRevisionClaim(revision);
|
final String resourceIdentifier = ResourceFactory.getTenantResource().getIdentifier() + "/" + userGroupId;
|
||||||
final NiFiUser nifiUser = NiFiUserUtils.getNiFiUser();
|
final UserGroupDTO snapshot = deleteComponent(
|
||||||
|
revision,
|
||||||
// perform the deletion
|
resourceIdentifier,
|
||||||
final UserGroupDTO snapshot = revisionManager.deleteRevision(claim, nifiUser, () -> {
|
() -> userGroupDAO.deleteUserGroup(userGroupId),
|
||||||
logger.debug("Attempting to delete component {} with claim {}", userGroup, claim);
|
false, // no user group specific policies to remove
|
||||||
|
dtoFactory.createUserGroupDto(userGroup, users));
|
||||||
userGroupDAO.deleteUserGroup(userGroupId);
|
|
||||||
|
|
||||||
// save the flow
|
|
||||||
controllerFacade.save();
|
|
||||||
logger.debug("Deletion of component {} was successful", userGroup);
|
|
||||||
|
|
||||||
return dtoFactory.createUserGroupDto(userGroup, users);
|
|
||||||
});
|
|
||||||
|
|
||||||
return entityFactory.createUserGroupEntity(snapshot, null, null);
|
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 Set<TenantEntity> users = accessPolicy != null ? accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) : null;
|
||||||
final AccessPolicyDTO snapshot = deleteComponent(
|
final AccessPolicyDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
authorizableLookup.getAccessPolicyById(accessPolicyId),
|
accessPolicy.getResource(),
|
||||||
() -> accessPolicyDAO.deleteAccessPolicy(accessPolicyId),
|
() -> accessPolicyDAO.deleteAccessPolicy(accessPolicyId),
|
||||||
|
false, // no need to clean up any policies as it's already been removed above
|
||||||
dtoFactory.createAccessPolicyDto(accessPolicy, userGroups,
|
dtoFactory.createAccessPolicyDto(accessPolicy, userGroups,
|
||||||
users));
|
users));
|
||||||
|
|
||||||
|
@ -975,8 +964,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final Funnel funnel = funnelDAO.getFunnel(funnelId);
|
final Funnel funnel = funnelDAO.getFunnel(funnelId);
|
||||||
final FunnelDTO snapshot = deleteComponent(
|
final FunnelDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
funnel,
|
funnel.getResource().getIdentifier(),
|
||||||
() -> funnelDAO.deleteFunnel(funnelId),
|
() -> funnelDAO.deleteFunnel(funnelId),
|
||||||
|
true,
|
||||||
dtoFactory.createFunnelDto(funnel));
|
dtoFactory.createFunnelDto(funnel));
|
||||||
|
|
||||||
return entityFactory.createFunnelEntity(snapshot, null, null);
|
return entityFactory.createFunnelEntity(snapshot, null, null);
|
||||||
|
@ -986,47 +976,49 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
* Deletes a component using the Optimistic Locking Manager
|
* Deletes a component using the Optimistic Locking Manager
|
||||||
*
|
*
|
||||||
* @param revision the current revision
|
* @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 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
|
* @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 RevisionClaim claim = new StandardRevisionClaim(revision);
|
||||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||||
|
|
||||||
return revisionManager.deleteRevision(claim, user, new DeleteRevisionTask<D>() {
|
return revisionManager.deleteRevision(claim, user, new DeleteRevisionTask<D>() {
|
||||||
@Override
|
@Override
|
||||||
public D performTask() {
|
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();
|
deleteAction.run();
|
||||||
|
|
||||||
// save the flow
|
// save the flow
|
||||||
controllerFacade.save();
|
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
|
// clean up the policy if necessary and configured with a policy based authorizer
|
||||||
if (authorizer instanceof AbstractPolicyBasedAuthorizer) {
|
if (cleanUpPolicies && authorizer instanceof AbstractPolicyBasedAuthorizer) {
|
||||||
try {
|
try {
|
||||||
// since the component is being deleted, also delete any relevant read access policies
|
// since the component is being deleted, also delete any relevant read access policies
|
||||||
final AccessPolicy readPolicy = accessPolicyDAO.getAccessPolicy(RequestAction.READ, authorizable);
|
final AccessPolicy readPolicy = accessPolicyDAO.getAccessPolicy(RequestAction.READ, resourceIdentifier);
|
||||||
if (authorizable.getResource().getIdentifier().equals(readPolicy.getResource())) {
|
if (readPolicy != null) {
|
||||||
accessPolicyDAO.deleteAccessPolicy(readPolicy.getIdentifier());
|
accessPolicyDAO.deleteAccessPolicy(readPolicy.getIdentifier());
|
||||||
}
|
}
|
||||||
} catch (final ResourceNotFoundException e) {
|
|
||||||
// no policy exists for this component... no worries
|
|
||||||
} catch (final Exception e) {
|
} 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 {
|
try {
|
||||||
// since the component is being deleted, also delete any relevant write access policies
|
// since the component is being deleted, also delete any relevant write access policies
|
||||||
final AccessPolicy writePolicy = accessPolicyDAO.getAccessPolicy(RequestAction.WRITE, authorizable);
|
final AccessPolicy writePolicy = accessPolicyDAO.getAccessPolicy(RequestAction.WRITE, resourceIdentifier);
|
||||||
if (authorizable.getResource().getIdentifier().equals(writePolicy.getResource())) {
|
if (writePolicy != null) {
|
||||||
accessPolicyDAO.deleteAccessPolicy(writePolicy.getIdentifier());
|
accessPolicyDAO.deleteAccessPolicy(writePolicy.getIdentifier());
|
||||||
}
|
}
|
||||||
} catch (final ResourceNotFoundException e) {
|
} catch (final ResourceNotFoundException e) {
|
||||||
// no policy exists for this component... no worries
|
// no policy exists for this component... no worries
|
||||||
} catch (final Exception e) {
|
} 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 Port port = inputPortDAO.getPort(inputPortId);
|
||||||
final PortDTO snapshot = deleteComponent(
|
final PortDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
port,
|
port.getResource().getIdentifier(),
|
||||||
() -> inputPortDAO.deletePort(inputPortId),
|
() -> inputPortDAO.deletePort(inputPortId),
|
||||||
|
true,
|
||||||
dtoFactory.createPortDto(port));
|
dtoFactory.createPortDto(port));
|
||||||
|
|
||||||
return entityFactory.createPortEntity(snapshot, null, null, null, null);
|
return entityFactory.createPortEntity(snapshot, null, null, null, null);
|
||||||
|
@ -1083,8 +1076,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final Port port = outputPortDAO.getPort(outputPortId);
|
final Port port = outputPortDAO.getPort(outputPortId);
|
||||||
final PortDTO snapshot = deleteComponent(
|
final PortDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
port,
|
port.getResource().getIdentifier(),
|
||||||
() -> outputPortDAO.deletePort(outputPortId),
|
() -> outputPortDAO.deletePort(outputPortId),
|
||||||
|
true,
|
||||||
dtoFactory.createPortDto(port));
|
dtoFactory.createPortDto(port));
|
||||||
|
|
||||||
return entityFactory.createPortEntity(snapshot, null, null, null, null);
|
return entityFactory.createPortEntity(snapshot, null, null, null, null);
|
||||||
|
@ -1095,8 +1089,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
|
final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
|
||||||
final ProcessGroupDTO snapshot = deleteComponent(
|
final ProcessGroupDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
processGroup,
|
processGroup.getResource().getIdentifier(),
|
||||||
() -> processGroupDAO.deleteProcessGroup(groupId),
|
() -> processGroupDAO.deleteProcessGroup(groupId),
|
||||||
|
true,
|
||||||
dtoFactory.createProcessGroupDto(processGroup));
|
dtoFactory.createProcessGroupDto(processGroup));
|
||||||
|
|
||||||
return entityFactory.createProcessGroupEntity(snapshot, null, null, null, null);
|
return entityFactory.createProcessGroupEntity(snapshot, null, null, null, null);
|
||||||
|
@ -1107,8 +1102,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final RemoteProcessGroup remoteProcessGroup = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupId);
|
final RemoteProcessGroup remoteProcessGroup = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupId);
|
||||||
final RemoteProcessGroupDTO snapshot = deleteComponent(
|
final RemoteProcessGroupDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
remoteProcessGroup,
|
remoteProcessGroup.getResource().getIdentifier(),
|
||||||
() -> remoteProcessGroupDAO.deleteRemoteProcessGroup(remoteProcessGroupId),
|
() -> remoteProcessGroupDAO.deleteRemoteProcessGroup(remoteProcessGroupId),
|
||||||
|
true,
|
||||||
dtoFactory.createRemoteProcessGroupDto(remoteProcessGroup));
|
dtoFactory.createRemoteProcessGroupDto(remoteProcessGroup));
|
||||||
|
|
||||||
return entityFactory.createRemoteProcessGroupEntity(snapshot, null, null, null, null);
|
return entityFactory.createRemoteProcessGroupEntity(snapshot, null, null, null, null);
|
||||||
|
@ -1740,8 +1736,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final ControllerServiceNode controllerService = controllerServiceDAO.getControllerService(controllerServiceId);
|
final ControllerServiceNode controllerService = controllerServiceDAO.getControllerService(controllerServiceId);
|
||||||
final ControllerServiceDTO snapshot = deleteComponent(
|
final ControllerServiceDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
controllerService,
|
controllerService.getResource().getIdentifier(),
|
||||||
() -> controllerServiceDAO.deleteControllerService(controllerServiceId),
|
() -> controllerServiceDAO.deleteControllerService(controllerServiceId),
|
||||||
|
true,
|
||||||
dtoFactory.createControllerServiceDto(controllerService));
|
dtoFactory.createControllerServiceDto(controllerService));
|
||||||
|
|
||||||
return entityFactory.createControllerServiceEntity(snapshot, null, null, null);
|
return entityFactory.createControllerServiceEntity(snapshot, null, null, null);
|
||||||
|
@ -1793,8 +1790,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final ReportingTaskNode reportingTask = reportingTaskDAO.getReportingTask(reportingTaskId);
|
final ReportingTaskNode reportingTask = reportingTaskDAO.getReportingTask(reportingTaskId);
|
||||||
final ReportingTaskDTO snapshot = deleteComponent(
|
final ReportingTaskDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
reportingTask,
|
reportingTask.getResource().getIdentifier(),
|
||||||
() -> reportingTaskDAO.deleteReportingTask(reportingTaskId),
|
() -> reportingTaskDAO.deleteReportingTask(reportingTaskId),
|
||||||
|
true,
|
||||||
dtoFactory.createReportingTaskDto(reportingTask));
|
dtoFactory.createReportingTaskDto(reportingTask));
|
||||||
|
|
||||||
return entityFactory.createReportingTaskEntity(snapshot, null, null, null);
|
return entityFactory.createReportingTaskEntity(snapshot, null, null, null);
|
||||||
|
|
|
@ -83,9 +83,7 @@ public class AccessPolicyResource extends ApplicationResource {
|
||||||
* @return accessPolicyEntity
|
* @return accessPolicyEntity
|
||||||
*/
|
*/
|
||||||
public AccessPolicyEntity populateRemainingAccessPolicyEntityContent(AccessPolicyEntity accessPolicyEntity) {
|
public AccessPolicyEntity populateRemainingAccessPolicyEntityContent(AccessPolicyEntity accessPolicyEntity) {
|
||||||
if (accessPolicyEntity.getComponent() != null) {
|
accessPolicyEntity.setUri(generateResourceUri("policies", accessPolicyEntity.getId()));
|
||||||
accessPolicyEntity.setUri(generateResourceUri("policies", accessPolicyEntity.getId()));
|
|
||||||
}
|
|
||||||
return accessPolicyEntity;
|
return accessPolicyEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +227,7 @@ public class AccessPolicyResource extends ApplicationResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the access policy id as appropriate
|
// set the access policy id as appropriate
|
||||||
accessPolicyEntity.getComponent().setId(generateUuid());
|
requestAccessPolicy.setId(generateUuid());
|
||||||
|
|
||||||
// get revision from the config
|
// get revision from the config
|
||||||
final RevisionDTO revisionDTO = accessPolicyEntity.getRevision();
|
final RevisionDTO revisionDTO = accessPolicyEntity.getRevision();
|
||||||
|
@ -286,7 +284,7 @@ public class AccessPolicyResource extends ApplicationResource {
|
||||||
// authorize access
|
// authorize access
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
Authorizable authorizable = lookup.getAccessPolicyById(id);
|
Authorizable authorizable = lookup.getAccessPolicyById(id);
|
||||||
authorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
authorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
|
||||||
});
|
});
|
||||||
|
|
||||||
// get the access policy
|
// get the access policy
|
||||||
|
@ -438,7 +436,7 @@ public class AccessPolicyResource extends ApplicationResource {
|
||||||
revision,
|
revision,
|
||||||
lookup -> {
|
lookup -> {
|
||||||
final Authorizable accessPolicy = lookup.getAccessPolicyById(id);
|
final Authorizable accessPolicy = lookup.getAccessPolicyById(id);
|
||||||
accessPolicy.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
|
accessPolicy.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
||||||
},
|
},
|
||||||
() -> {
|
() -> {
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,6 +24,7 @@ import com.wordnik.swagger.annotations.ApiResponses;
|
||||||
import com.wordnik.swagger.annotations.Authorization;
|
import com.wordnik.swagger.annotations.Authorization;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.nifi.authorization.Authorizer;
|
import org.apache.nifi.authorization.Authorizer;
|
||||||
|
import org.apache.nifi.authorization.ConnectionAuthorizable;
|
||||||
import org.apache.nifi.authorization.RequestAction;
|
import org.apache.nifi.authorization.RequestAction;
|
||||||
import org.apache.nifi.authorization.resource.Authorizable;
|
import org.apache.nifi.authorization.resource.Authorizable;
|
||||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||||
|
@ -120,7 +121,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
@GET
|
@GET
|
||||||
@Consumes(MediaType.WILDCARD)
|
@Consumes(MediaType.WILDCARD)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("{connection-id}/flowfiles/{flowfile-uuid}")
|
@Path("{id}/flowfiles/{flowfile-uuid}")
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
value = "Gets a FlowFile from a Connection.",
|
value = "Gets a FlowFile from a Connection.",
|
||||||
|
@ -142,7 +143,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
value = "The connection id.",
|
value = "The connection id.",
|
||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
@PathParam("connection-id") final String connectionId,
|
@PathParam("id") final String connectionId,
|
||||||
@ApiParam(
|
@ApiParam(
|
||||||
value = "The flowfile uuid.",
|
value = "The flowfile uuid.",
|
||||||
required = true
|
required = true
|
||||||
|
@ -170,11 +171,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// authorize access
|
// NOTE - deferred authorization so we can consider flowfile attributes in the access decision
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
|
||||||
final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
|
|
||||||
connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
|
||||||
});
|
|
||||||
|
|
||||||
// get the flowfile
|
// get the flowfile
|
||||||
final FlowFileDTO flowfileDto = serviceFacade.getFlowFile(connectionId, flowFileUuid);
|
final FlowFileDTO flowfileDto = serviceFacade.getFlowFile(connectionId, flowFileUuid);
|
||||||
|
@ -200,7 +197,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
@GET
|
@GET
|
||||||
@Consumes(MediaType.WILDCARD)
|
@Consumes(MediaType.WILDCARD)
|
||||||
@Produces(MediaType.WILDCARD)
|
@Produces(MediaType.WILDCARD)
|
||||||
@Path("{connection-id}/flowfiles/{flowfile-uuid}/content")
|
@Path("{id}/flowfiles/{flowfile-uuid}/content")
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
value = "Gets the content for a FlowFile in a Connection.",
|
value = "Gets the content for a FlowFile in a Connection.",
|
||||||
|
@ -227,7 +224,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
value = "The connection id.",
|
value = "The connection id.",
|
||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
@PathParam("connection-id") final String connectionId,
|
@PathParam("id") final String connectionId,
|
||||||
@ApiParam(
|
@ApiParam(
|
||||||
value = "The flowfile uuid.",
|
value = "The flowfile uuid.",
|
||||||
required = true
|
required = true
|
||||||
|
@ -255,11 +252,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// authorize access
|
// NOTE - deferred authorization so we can consider flowfile attributes in the access decision
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
|
||||||
final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
|
|
||||||
connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
|
||||||
});
|
|
||||||
|
|
||||||
// get the uri of the request
|
// get the uri of the request
|
||||||
final String uri = generateResourceUri("flowfile-queues", connectionId, "flowfiles", flowFileUuid, "content");
|
final String uri = generateResourceUri("flowfile-queues", connectionId, "flowfiles", flowFileUuid, "content");
|
||||||
|
@ -300,7 +293,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.WILDCARD)
|
@Consumes(MediaType.WILDCARD)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("{connection-id}/listing-requests")
|
@Path("{id}/listing-requests")
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
value = "Lists the contents of the queue in this connection.",
|
value = "Lists the contents of the queue in this connection.",
|
||||||
|
@ -325,7 +318,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
value = "The connection id.",
|
value = "The connection id.",
|
||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
@PathParam("connection-id") final String id) {
|
@PathParam("id") final String id) {
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
if (isReplicateRequest()) {
|
||||||
return replicate(HttpMethod.POST);
|
return replicate(HttpMethod.POST);
|
||||||
|
@ -336,8 +329,9 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
||||||
// authorize access
|
// authorize access
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
final Authorizable connection = lookup.getConnection(id).getAuthorizable();
|
final ConnectionAuthorizable connAuth = lookup.getConnection(id);
|
||||||
connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (validationPhase) {
|
if (validationPhase) {
|
||||||
|
@ -371,7 +365,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
@GET
|
@GET
|
||||||
@Consumes(MediaType.WILDCARD)
|
@Consumes(MediaType.WILDCARD)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("{connection-id}/listing-requests/{listing-request-id}")
|
@Path("{id}/listing-requests/{listing-request-id}")
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
value = "Gets the current status of a listing request for the specified connection.",
|
value = "Gets the current status of a listing request for the specified connection.",
|
||||||
|
@ -394,7 +388,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
value = "The connection id.",
|
value = "The connection id.",
|
||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
@PathParam("connection-id") final String connectionId,
|
@PathParam("id") final String connectionId,
|
||||||
@ApiParam(
|
@ApiParam(
|
||||||
value = "The listing request id.",
|
value = "The listing request id.",
|
||||||
required = true
|
required = true
|
||||||
|
@ -407,8 +401,9 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
|
|
||||||
// authorize access
|
// authorize access
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
|
final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
|
||||||
connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
|
||||||
});
|
});
|
||||||
|
|
||||||
// get the listing request
|
// get the listing request
|
||||||
|
@ -433,7 +428,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
@DELETE
|
@DELETE
|
||||||
@Consumes(MediaType.WILDCARD)
|
@Consumes(MediaType.WILDCARD)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("{connection-id}/listing-requests/{listing-request-id}")
|
@Path("{id}/listing-requests/{listing-request-id}")
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
value = "Cancels and/or removes a request to list the contents of this connection.",
|
value = "Cancels and/or removes a request to list the contents of this connection.",
|
||||||
|
@ -457,7 +452,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
value = "The connection id.",
|
value = "The connection id.",
|
||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
@PathParam("connection-id") final String connectionId,
|
@PathParam("id") final String connectionId,
|
||||||
@ApiParam(
|
@ApiParam(
|
||||||
value = "The listing request id.",
|
value = "The listing request id.",
|
||||||
required = true
|
required = true
|
||||||
|
@ -473,8 +468,9 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
||||||
// authorize access
|
// authorize access
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
|
final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
|
||||||
connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (validationPhase) {
|
if (validationPhase) {
|
||||||
|
@ -507,7 +503,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.WILDCARD)
|
@Consumes(MediaType.WILDCARD)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("{connection-id}/drop-requests")
|
@Path("{id}/drop-requests")
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
value = "Creates a request to drop the contents of the queue in this connection.",
|
value = "Creates a request to drop the contents of the queue in this connection.",
|
||||||
|
@ -532,7 +528,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
value = "The connection id.",
|
value = "The connection id.",
|
||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
@PathParam("connection-id") final String id) {
|
@PathParam("id") final String id) {
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
if (isReplicateRequest()) {
|
||||||
return replicate(HttpMethod.POST);
|
return replicate(HttpMethod.POST);
|
||||||
|
@ -543,8 +539,9 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
||||||
// authorize access
|
// authorize access
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
final Authorizable connection = lookup.getConnection(id).getAuthorizable();
|
final ConnectionAuthorizable connAuth = lookup.getConnection(id);
|
||||||
connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (validationPhase) {
|
if (validationPhase) {
|
||||||
|
@ -577,7 +574,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
@GET
|
@GET
|
||||||
@Consumes(MediaType.WILDCARD)
|
@Consumes(MediaType.WILDCARD)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("{connection-id}/drop-requests/{drop-request-id}")
|
@Path("{id}/drop-requests/{drop-request-id}")
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
value = "Gets the current status of a drop request for the specified connection.",
|
value = "Gets the current status of a drop request for the specified connection.",
|
||||||
|
@ -600,7 +597,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
value = "The connection id.",
|
value = "The connection id.",
|
||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
@PathParam("connection-id") final String connectionId,
|
@PathParam("id") final String connectionId,
|
||||||
@ApiParam(
|
@ApiParam(
|
||||||
value = "The drop request id.",
|
value = "The drop request id.",
|
||||||
required = true
|
required = true
|
||||||
|
@ -613,8 +610,9 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
|
|
||||||
// authorize access
|
// authorize access
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
|
final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
|
||||||
connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
||||||
});
|
});
|
||||||
|
|
||||||
// get the drop request
|
// get the drop request
|
||||||
|
@ -639,7 +637,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
@DELETE
|
@DELETE
|
||||||
@Consumes(MediaType.WILDCARD)
|
@Consumes(MediaType.WILDCARD)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("{connection-id}/drop-requests/{drop-request-id}")
|
@Path("{id}/drop-requests/{drop-request-id}")
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
value = "Cancels and/or removes a request to drop the contents of this connection.",
|
value = "Cancels and/or removes a request to drop the contents of this connection.",
|
||||||
|
@ -663,7 +661,7 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
value = "The connection id.",
|
value = "The connection id.",
|
||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
@PathParam("connection-id") final String connectionId,
|
@PathParam("id") final String connectionId,
|
||||||
@ApiParam(
|
@ApiParam(
|
||||||
value = "The drop request id.",
|
value = "The drop request id.",
|
||||||
required = true
|
required = true
|
||||||
|
@ -679,8 +677,9 @@ public class FlowFileQueueResource extends ApplicationResource {
|
||||||
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
||||||
// authorize access
|
// authorize access
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
final Authorizable connection = lookup.getConnection(connectionId).getAuthorizable();
|
final ConnectionAuthorizable connAuth = lookup.getConnection(connectionId);
|
||||||
connection.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
final Authorizable dataAuthorizable = lookup.getData(connAuth.getSource().getIdentifier());
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (validationPhase) {
|
if (validationPhase) {
|
||||||
|
|
|
@ -30,7 +30,6 @@ import org.apache.nifi.authorization.resource.ResourceFactory;
|
||||||
import org.apache.nifi.authorization.resource.ResourceType;
|
import org.apache.nifi.authorization.resource.ResourceType;
|
||||||
import org.apache.nifi.authorization.user.NiFiUser;
|
import org.apache.nifi.authorization.user.NiFiUser;
|
||||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||||
import org.apache.nifi.authorization.user.StandardNiFiUser;
|
|
||||||
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
|
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
|
||||||
import org.apache.nifi.cluster.protocol.NodeIdentifier;
|
import org.apache.nifi.cluster.protocol.NodeIdentifier;
|
||||||
import org.apache.nifi.components.PropertyDescriptor;
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
@ -69,8 +68,8 @@ import org.apache.nifi.nar.NarCloseable;
|
||||||
import org.apache.nifi.processor.DataUnit;
|
import org.apache.nifi.processor.DataUnit;
|
||||||
import org.apache.nifi.processor.Processor;
|
import org.apache.nifi.processor.Processor;
|
||||||
import org.apache.nifi.processor.Relationship;
|
import org.apache.nifi.processor.Relationship;
|
||||||
import org.apache.nifi.provenance.ProvenanceRepository;
|
|
||||||
import org.apache.nifi.provenance.ProvenanceEventRecord;
|
import org.apache.nifi.provenance.ProvenanceEventRecord;
|
||||||
|
import org.apache.nifi.provenance.ProvenanceRepository;
|
||||||
import org.apache.nifi.provenance.SearchableFields;
|
import org.apache.nifi.provenance.SearchableFields;
|
||||||
import org.apache.nifi.provenance.lineage.ComputeLineageSubmission;
|
import org.apache.nifi.provenance.lineage.ComputeLineageSubmission;
|
||||||
import org.apache.nifi.provenance.search.Query;
|
import org.apache.nifi.provenance.search.Query;
|
||||||
|
@ -109,7 +108,6 @@ import org.apache.nifi.web.api.dto.search.ComponentSearchResultDTO;
|
||||||
import org.apache.nifi.web.api.dto.search.SearchResultsDTO;
|
import org.apache.nifi.web.api.dto.search.SearchResultsDTO;
|
||||||
import org.apache.nifi.web.api.dto.status.ControllerStatusDTO;
|
import org.apache.nifi.web.api.dto.status.ControllerStatusDTO;
|
||||||
import org.apache.nifi.web.api.dto.status.StatusHistoryDTO;
|
import org.apache.nifi.web.api.dto.status.StatusHistoryDTO;
|
||||||
import org.apache.nifi.web.security.ProxiedEntitiesUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -767,7 +765,7 @@ public class ControllerFacade implements Authorizable {
|
||||||
// add each processor
|
// add each processor
|
||||||
for (final ProcessorNode processor : root.findAllProcessors()) {
|
for (final ProcessorNode processor : root.findAllProcessors()) {
|
||||||
resources.add(ResourceFactory.getComponentResource(ResourceType.Processor, processor.getIdentifier(), processor.getName()));
|
resources.add(ResourceFactory.getComponentResource(ResourceType.Processor, processor.getIdentifier(), processor.getName()));
|
||||||
resources.add(ResourceFactory.getProvenanceEventResource(processor.getResource()));
|
resources.add(ResourceFactory.getDataResource(processor.getResource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// add each label
|
// add each label
|
||||||
|
@ -778,25 +776,25 @@ public class ControllerFacade implements Authorizable {
|
||||||
// add each process group
|
// add each process group
|
||||||
for (final ProcessGroup processGroup : root.findAllProcessGroups()) {
|
for (final ProcessGroup processGroup : root.findAllProcessGroups()) {
|
||||||
resources.add(ResourceFactory.getComponentResource(ResourceType.ProcessGroup, processGroup.getIdentifier(), processGroup.getName()));
|
resources.add(ResourceFactory.getComponentResource(ResourceType.ProcessGroup, processGroup.getIdentifier(), processGroup.getName()));
|
||||||
resources.add(ResourceFactory.getProvenanceEventResource(processGroup.getResource()));
|
resources.add(ResourceFactory.getDataResource(processGroup.getResource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// add each remote process group
|
// add each remote process group
|
||||||
for (final RemoteProcessGroup remoteProcessGroup : root.findAllRemoteProcessGroups()) {
|
for (final RemoteProcessGroup remoteProcessGroup : root.findAllRemoteProcessGroups()) {
|
||||||
resources.add(ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup, remoteProcessGroup.getIdentifier(), remoteProcessGroup.getName()));
|
resources.add(ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup, remoteProcessGroup.getIdentifier(), remoteProcessGroup.getName()));
|
||||||
resources.add(ResourceFactory.getProvenanceEventResource(remoteProcessGroup.getResource()));
|
resources.add(ResourceFactory.getDataResource(remoteProcessGroup.getResource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// add each input port
|
// add each input port
|
||||||
for (final Port inputPort : root.findAllInputPorts()) {
|
for (final Port inputPort : root.findAllInputPorts()) {
|
||||||
resources.add(ResourceFactory.getComponentResource(ResourceType.InputPort, inputPort.getIdentifier(), inputPort.getName()));
|
resources.add(ResourceFactory.getComponentResource(ResourceType.InputPort, inputPort.getIdentifier(), inputPort.getName()));
|
||||||
resources.add(ResourceFactory.getProvenanceEventResource(inputPort.getResource()));
|
resources.add(ResourceFactory.getDataResource(inputPort.getResource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// add each output port
|
// add each output port
|
||||||
for (final Port outputPort : root.findAllOutputPorts()) {
|
for (final Port outputPort : root.findAllOutputPorts()) {
|
||||||
resources.add(ResourceFactory.getComponentResource(ResourceType.OutputPort, outputPort.getIdentifier(), outputPort.getName()));
|
resources.add(ResourceFactory.getComponentResource(ResourceType.OutputPort, outputPort.getIdentifier(), outputPort.getName()));
|
||||||
resources.add(ResourceFactory.getProvenanceEventResource(outputPort.getResource()));
|
resources.add(ResourceFactory.getDataResource(outputPort.getResource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// add each controller service
|
// add each controller service
|
||||||
|
@ -1087,7 +1085,7 @@ public class ControllerFacade implements Authorizable {
|
||||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||||
|
|
||||||
// get the event in order to get the filename
|
// get the event in order to get the filename
|
||||||
final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId, NiFiUserUtils.getNiFiUser());
|
final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId);
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
throw new ResourceNotFoundException("Unable to find the specified event.");
|
throw new ResourceNotFoundException("Unable to find the specified event.");
|
||||||
}
|
}
|
||||||
|
@ -1101,7 +1099,8 @@ public class ControllerFacade implements Authorizable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// authorize the event
|
// authorize the event
|
||||||
authorizeEvent(event.getComponentId(), attributes);
|
final Authorizable dataAuthorizable = flowController.createDataAuthorizable(event.getComponentId());
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.READ, user, attributes);
|
||||||
|
|
||||||
// get the filename and fall back to the identifier (should never happen)
|
// get the filename and fall back to the identifier (should never happen)
|
||||||
String filename = attributes.get(CoreAttributes.FILENAME.key());
|
String filename = attributes.get(CoreAttributes.FILENAME.key());
|
||||||
|
@ -1137,7 +1136,7 @@ public class ControllerFacade implements Authorizable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// lookup the original event
|
// lookup the original event
|
||||||
final ProvenanceEventRecord originalEvent = flowController.getProvenanceRepository().getEvent(eventId, NiFiUserUtils.getNiFiUser());
|
final ProvenanceEventRecord originalEvent = flowController.getProvenanceRepository().getEvent(eventId);
|
||||||
if (originalEvent == null) {
|
if (originalEvent == null) {
|
||||||
throw new ResourceNotFoundException("Unable to find the specified event.");
|
throw new ResourceNotFoundException("Unable to find the specified event.");
|
||||||
}
|
}
|
||||||
|
@ -1155,67 +1154,6 @@ public class ControllerFacade implements Authorizable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Authorizes access to a provenance event generated by the specified component and containing the specified eventAttributes.
|
|
||||||
*
|
|
||||||
* @param componentId component id
|
|
||||||
* @param eventAttributes event attributes
|
|
||||||
*/
|
|
||||||
private AuthorizationResult checkAuthorizationForEvent(final String componentId, final Map<String, String> eventAttributes) {
|
|
||||||
AuthorizationResult result = null;
|
|
||||||
|
|
||||||
// calculate the dn chain
|
|
||||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
|
||||||
final List<String> dnChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
|
|
||||||
for (final String identity : dnChain) {
|
|
||||||
final Authorizable eventAuthorizable = flowController.createProvenanceAuthorizable(componentId);
|
|
||||||
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 = eventAuthorizable.checkAuthorization(authorizer, RequestAction.READ, chainUser, eventAttributes);
|
|
||||||
if (!Result.Approved.equals(result.getResult())) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
result = AuthorizationResult.denied();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authorizes access to a provenance event generated by the specified component and containing the specified eventAttributes.
|
|
||||||
*
|
|
||||||
* @param componentId component id
|
|
||||||
* @param eventAttributes event attributes
|
|
||||||
*/
|
|
||||||
private void authorizeEvent(final String componentId, final Map<String, String> eventAttributes) {
|
|
||||||
// calculate the dn chain
|
|
||||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
|
||||||
final List<String> dnChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
|
|
||||||
for (final String identity : dnChain) {
|
|
||||||
final Authorizable eventAuthorizable = flowController.createProvenanceAuthorizable(componentId);
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
eventAuthorizable.authorize(authorizer, RequestAction.READ, chainUser, eventAttributes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authorizes access to replay a specified provenance event.
|
* Authorizes access to replay a specified provenance event.
|
||||||
*
|
*
|
||||||
|
@ -1229,16 +1167,17 @@ public class ControllerFacade implements Authorizable {
|
||||||
return AuthorizationResult.denied();
|
return AuthorizationResult.denied();
|
||||||
}
|
}
|
||||||
|
|
||||||
final AuthorizationResult result = checkAuthorizationForEvent(componentId, eventAttributes);
|
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||||
|
final Authorizable dataAuthorizable = flowController.createDataAuthorizable(componentId);
|
||||||
|
|
||||||
|
// ensure we can read the data
|
||||||
|
final AuthorizationResult result = dataAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, eventAttributes);
|
||||||
if (!Result.Approved.equals(result.getResult())) {
|
if (!Result.Approved.equals(result.getResult())) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// authorize write permissions for the queue
|
// ensure we can write the data
|
||||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
return dataAuthorizable.checkAuthorization(authorizer, RequestAction.WRITE, user, eventAttributes);
|
||||||
final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId());
|
|
||||||
final Connection connection = rootGroup.findConnection(connectionId);
|
|
||||||
return connection.checkAuthorization(authorizer, RequestAction.WRITE, user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1254,13 +1193,12 @@ public class ControllerFacade implements Authorizable {
|
||||||
throw new AccessDeniedException("The connection id is unknown.");
|
throw new AccessDeniedException("The connection id is unknown.");
|
||||||
}
|
}
|
||||||
|
|
||||||
authorizeEvent(componentId, eventAttributes);
|
|
||||||
|
|
||||||
// authorize write permissions for the queue
|
|
||||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||||
final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId());
|
final Authorizable dataAuthorizable = flowController.createDataAuthorizable(componentId);
|
||||||
final Connection connection = rootGroup.findConnection(connectionId);
|
|
||||||
connection.authorize(authorizer, RequestAction.WRITE, user);
|
// ensure we can read and write the data
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.READ, user, eventAttributes);
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.WRITE, user, eventAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1271,14 +1209,15 @@ public class ControllerFacade implements Authorizable {
|
||||||
*/
|
*/
|
||||||
public ProvenanceEventDTO getProvenanceEvent(final Long eventId) {
|
public ProvenanceEventDTO getProvenanceEvent(final Long eventId) {
|
||||||
try {
|
try {
|
||||||
final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId, NiFiUserUtils.getNiFiUser());
|
final ProvenanceEventRecord event = flowController.getProvenanceRepository().getEvent(eventId);
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
throw new ResourceNotFoundException("Unable to find the specified event.");
|
throw new ResourceNotFoundException("Unable to find the specified event.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the flowfile attributes and authorize the event
|
// get the flowfile attributes and authorize the event
|
||||||
final Map<String, String> attributes = event.getAttributes();
|
final Map<String, String> attributes = event.getAttributes();
|
||||||
authorizeEvent(event.getComponentId(), attributes);
|
final Authorizable dataAuthorizable = flowController.createDataAuthorizable(event.getComponentId());
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser(), attributes);
|
||||||
|
|
||||||
// convert the event
|
// convert the event
|
||||||
return createProvenanceEventDto(event);
|
return createProvenanceEventDto(event);
|
||||||
|
@ -1293,8 +1232,8 @@ public class ControllerFacade implements Authorizable {
|
||||||
* @param componentId component id
|
* @param componentId component id
|
||||||
* @return authorizable
|
* @return authorizable
|
||||||
*/
|
*/
|
||||||
public Authorizable getProvenanceEventAuthorizable(final String componentId) {
|
public Authorizable getDataAuthorizable(final String componentId) {
|
||||||
return flowController.createProvenanceAuthorizable(componentId);
|
return flowController.createDataAuthorizable(componentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -46,7 +46,18 @@ public interface AccessPolicyDAO {
|
||||||
AccessPolicy getAccessPolicy(String accessPolicyId);
|
AccessPolicy getAccessPolicy(String accessPolicyId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the access policy according to the action and authorizable.
|
* Gets the access policy according to the action and authorizable. Will return null
|
||||||
|
* if no policy exists for the specific resource.
|
||||||
|
*
|
||||||
|
* @param requestAction action
|
||||||
|
* @param resource resource
|
||||||
|
* @return access policy
|
||||||
|
*/
|
||||||
|
AccessPolicy getAccessPolicy(RequestAction requestAction, String resource);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the access policy according to the action and authorizable. Will return the
|
||||||
|
* effective policy if no policy exists for the specific authorizable.
|
||||||
*
|
*
|
||||||
* @param requestAction action
|
* @param requestAction action
|
||||||
* @param authorizable authorizable
|
* @param authorizable authorizable
|
||||||
|
|
|
@ -16,16 +16,11 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.web.dao.impl;
|
package org.apache.nifi.web.dao.impl;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
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.Authorizer;
|
||||||
import org.apache.nifi.authorization.RequestAction;
|
import org.apache.nifi.authorization.RequestAction;
|
||||||
import org.apache.nifi.authorization.UserContextKeys;
|
import org.apache.nifi.authorization.resource.Authorizable;
|
||||||
import org.apache.nifi.authorization.user.NiFiUser;
|
import org.apache.nifi.authorization.user.NiFiUser;
|
||||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||||
import org.apache.nifi.authorization.user.StandardNiFiUser;
|
|
||||||
import org.apache.nifi.connectable.Connectable;
|
import org.apache.nifi.connectable.Connectable;
|
||||||
import org.apache.nifi.connectable.ConnectableType;
|
import org.apache.nifi.connectable.ConnectableType;
|
||||||
import org.apache.nifi.connectable.Connection;
|
import org.apache.nifi.connectable.Connection;
|
||||||
|
@ -50,7 +45,6 @@ import org.apache.nifi.web.api.dto.ConnectableDTO;
|
||||||
import org.apache.nifi.web.api.dto.ConnectionDTO;
|
import org.apache.nifi.web.api.dto.ConnectionDTO;
|
||||||
import org.apache.nifi.web.api.dto.PositionDTO;
|
import org.apache.nifi.web.api.dto.PositionDTO;
|
||||||
import org.apache.nifi.web.dao.ConnectionDAO;
|
import org.apache.nifi.web.dao.ConnectionDAO;
|
||||||
import org.apache.nifi.web.security.ProxiedEntitiesUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -60,7 +54,6 @@ import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -139,6 +132,11 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO
|
||||||
throw new ResourceNotFoundException(String.format("The FlowFile with UUID %s is no longer in the active queue.", flowFileUuid));
|
throw new ResourceNotFoundException(String.format("The FlowFile with UUID %s is no longer in the active queue.", flowFileUuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the attributes and ensure appropriate access
|
||||||
|
final Map<String, String> attributes = flowFile.getAttributes();
|
||||||
|
final Authorizable dataAuthorizable = flowController.createDataAuthorizable(connection.getSource().getIdentifier());
|
||||||
|
dataAuthorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser(), attributes);
|
||||||
|
|
||||||
return flowFile;
|
return flowFile;
|
||||||
} catch (final IOException ioe) {
|
} catch (final IOException ioe) {
|
||||||
logger.error(String.format("Unable to get the flowfile (%s) at this time.", flowFileUuid), ioe);
|
logger.error(String.format("Unable to get the flowfile (%s) at this time.", flowFileUuid), ioe);
|
||||||
|
@ -597,26 +595,10 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO
|
||||||
throw new ResourceNotFoundException(String.format("The FlowFile with UUID %s is no longer in the active queue.", flowFileUuid));
|
throw new ResourceNotFoundException(String.format("The FlowFile with UUID %s is no longer in the active queue.", flowFileUuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the attributes and ensure appropriate access
|
||||||
final Map<String, String> attributes = flowFile.getAttributes();
|
final Map<String, String> attributes = flowFile.getAttributes();
|
||||||
|
final Authorizable dataAuthorizable = flowController.createDataAuthorizable(connection.getSource().getIdentifier());
|
||||||
// calculate the dn chain
|
dataAuthorizable.authorize(authorizer, RequestAction.READ, user, attributes);
|
||||||
final List<String> dnChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
|
|
||||||
dnChain.forEach(identity -> {
|
|
||||||
// build the request
|
|
||||||
final Map<String,String> userContext;
|
|
||||||
if (!StringUtils.isBlank(user.getClientAddress())) {
|
|
||||||
userContext = new HashMap<>();
|
|
||||||
userContext.put(UserContextKeys.CLIENT_ADDRESS.name(), user.getClientAddress());
|
|
||||||
} else {
|
|
||||||
userContext = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final NiFiUser chainUser = new StandardNiFiUser(identity, user.getClientAddress());
|
|
||||||
final AuthorizationResult result = connection.checkAuthorization(authorizer, RequestAction.WRITE, chainUser, attributes);
|
|
||||||
if (!Result.Approved.equals(result.getResult())) {
|
|
||||||
throw new AccessDeniedException(result.getExplanation());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// get the filename and fall back to the identifier (should never happen)
|
// get the filename and fall back to the identifier (should never happen)
|
||||||
String filename = attributes.get(CoreAttributes.FILENAME.key());
|
String filename = attributes.get(CoreAttributes.FILENAME.key());
|
||||||
|
|
|
@ -179,6 +179,11 @@ public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, UserGr
|
||||||
return accessPolicy;
|
return accessPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessPolicy getAccessPolicy(final RequestAction requestAction, final String resource) {
|
||||||
|
return findAccessPolicy(requestAction, resource);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessPolicy getAccessPolicy(final RequestAction requestAction, final Authorizable authorizable) {
|
public AccessPolicy getAccessPolicy(final RequestAction requestAction, final Authorizable authorizable) {
|
||||||
final String resource = authorizable.getResource().getIdentifier();
|
final String resource = authorizable.getResource().getIdentifier();
|
||||||
|
|
|
@ -16,16 +16,18 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.web.security;
|
package org.apache.nifi.web.security;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.nifi.authorization.user.NiFiUser;
|
||||||
|
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.nifi.authorization.user.NiFiUser;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.AuthenticationException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -72,33 +74,10 @@ public class ProxiedEntitiesUtils {
|
||||||
*/
|
*/
|
||||||
public static String buildProxiedEntitiesChainString(final NiFiUser user) {
|
public static String buildProxiedEntitiesChainString(final NiFiUser user) {
|
||||||
// calculate the dn chain
|
// calculate the dn chain
|
||||||
final List<String> proxyChain = buildProxiedEntitiesChain(user);
|
final List<String> proxyChain = NiFiUserUtils.buildProxiedEntitiesChain(user);
|
||||||
return formatProxyDn(StringUtils.join(proxyChain, "><"));
|
return formatProxyDn(StringUtils.join(proxyChain, "><"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the proxy chain from the specified request and user.
|
* Builds the proxy chain from the specified request and user.
|
||||||
*
|
*
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
body.login-body input, body.login-body textarea {
|
body.login-body input, body.login-body textarea {
|
||||||
width: 400px;
|
width: 412px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.login-container {
|
div.login-container {
|
||||||
|
|
|
@ -999,8 +999,9 @@ nf.Actions = (function () {
|
||||||
$('#drop-request-status-message').text(dropRequest.state);
|
$('#drop-request-status-message').text(dropRequest.state);
|
||||||
|
|
||||||
// update the current number of enqueued flowfiles
|
// update the current number of enqueued flowfiles
|
||||||
if (nf.Common.isDefinedAndNotNull(connection.status) && nf.Common.isDefinedAndNotNull(dropRequest.currentCount)) {
|
if (nf.Common.isDefinedAndNotNull(dropRequest.currentCount)) {
|
||||||
connection.status.queued = dropRequest.current;
|
connection.status.queued = dropRequest.current;
|
||||||
|
connection.status.aggregateSnapshot.queued = dropRequest.current;
|
||||||
nf.Connection.refresh(connection.id);
|
nf.Connection.refresh(connection.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,13 +1029,19 @@ nf.Actions = (function () {
|
||||||
}).done(function (response) {
|
}).done(function (response) {
|
||||||
dropRequest = response.dropRequest;
|
dropRequest = response.dropRequest;
|
||||||
processDropRequest(nextDelay);
|
processDropRequest(nextDelay);
|
||||||
}).fail(completeDropRequest);
|
}).fail(function (xhr, status, error) {
|
||||||
|
if (xhr.status === 403) {
|
||||||
|
nf.Common.handleAjaxError(xhr, status, error);
|
||||||
|
} else {
|
||||||
|
completeDropRequest()
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// issue the request to delete the flow files
|
// issue the request to delete the flow files
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: '../nifi-api/flowfile-queues/' + connection.id + '/drop-requests',
|
url: '../nifi-api/flowfile-queues/' + encodeURIComponent(connection.id) + '/drop-requests',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: 'application/json'
|
contentType: 'application/json'
|
||||||
}).done(function (response) {
|
}).done(function (response) {
|
||||||
|
@ -1047,7 +1054,13 @@ nf.Actions = (function () {
|
||||||
// process the drop request
|
// process the drop request
|
||||||
dropRequest = response.dropRequest;
|
dropRequest = response.dropRequest;
|
||||||
processDropRequest(1);
|
processDropRequest(1);
|
||||||
}).fail(completeDropRequest);
|
}).fail(function (xhr, status, error) {
|
||||||
|
if (xhr.status === 403) {
|
||||||
|
nf.Common.handleAjaxError(xhr, status, error);
|
||||||
|
} else {
|
||||||
|
completeDropRequest()
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -316,10 +316,6 @@ nf.ContextMenu = (function () {
|
||||||
* @param {selection} selection
|
* @param {selection} selection
|
||||||
*/
|
*/
|
||||||
var canEmptyQueue = function (selection) {
|
var canEmptyQueue = function (selection) {
|
||||||
if (nf.CanvasUtils.canModify(selection) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isConnection(selection);
|
return isConnection(selection);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -329,10 +325,6 @@ nf.ContextMenu = (function () {
|
||||||
* @param {selection} selection
|
* @param {selection} selection
|
||||||
*/
|
*/
|
||||||
var canListQueue = function (selection) {
|
var canListQueue = function (selection) {
|
||||||
if (nf.CanvasUtils.canModify(selection) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isConnection(selection);
|
return isConnection(selection);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -308,17 +308,13 @@ nf.PolicyManagement = (function () {
|
||||||
value: 'write-component',
|
value: 'write-component',
|
||||||
description: 'Allows users to modify component configuration details'
|
description: 'Allows users to modify component configuration details'
|
||||||
}, {
|
}, {
|
||||||
text: 'view the provenance events',
|
text: 'view the data',
|
||||||
value: 'read-provenance-events',
|
value: 'read-data',
|
||||||
description: 'Allows users to access provenance events and content for this component'
|
description: 'Allows users to view metadata and content for this component through provenance data and flowfile queues in outbound connections'
|
||||||
}, {
|
}, {
|
||||||
text: 'view the policies',
|
text: 'modify the data',
|
||||||
value: 'read-policies',
|
value: 'write-data',
|
||||||
description: 'Allows users to view the list of users who can view/modify this component'
|
description: 'Allows users to empty flowfile queues in outbound connections and submit replays'
|
||||||
}, {
|
|
||||||
text: 'modify the policies',
|
|
||||||
value: 'write-policies',
|
|
||||||
description: 'Allows users to modify the list of users who can view/modify this component'
|
|
||||||
}, {
|
}, {
|
||||||
text: 'receive data via site-to-site',
|
text: 'receive data via site-to-site',
|
||||||
value: 'write-receive-data',
|
value: 'write-receive-data',
|
||||||
|
@ -329,6 +325,14 @@ nf.PolicyManagement = (function () {
|
||||||
value: 'write-send-data',
|
value: 'write-send-data',
|
||||||
description: 'Allows this port to send data to these NiFi instances',
|
description: 'Allows this port to send data to these NiFi instances',
|
||||||
disabled: true
|
disabled: true
|
||||||
|
}, {
|
||||||
|
text: 'view the policies',
|
||||||
|
value: 'read-policies',
|
||||||
|
description: 'Allows users to view the list of users who can view/modify this component'
|
||||||
|
}, {
|
||||||
|
text: 'modify the policies',
|
||||||
|
value: 'write-policies',
|
||||||
|
description: 'Allows users to modify the list of users who can view/modify this component'
|
||||||
}],
|
}],
|
||||||
select: function (option) {
|
select: function (option) {
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
|
@ -338,9 +342,12 @@ nf.PolicyManagement = (function () {
|
||||||
$('#selected-policy-action').text('read');
|
$('#selected-policy-action').text('read');
|
||||||
} else if (option.value === 'write-component') {
|
} else if (option.value === 'write-component') {
|
||||||
$('#selected-policy-action').text('write');
|
$('#selected-policy-action').text('write');
|
||||||
} else if (option.value === 'read-provenance-events') {
|
} else if (option.value === 'read-data') {
|
||||||
$('#selected-policy-action').text('read');
|
$('#selected-policy-action').text('read');
|
||||||
resource = ('provenance-events/' + resource);
|
resource = ('data/' + resource);
|
||||||
|
} else if (option.value === 'write-data') {
|
||||||
|
$('#selected-policy-action').text('write');
|
||||||
|
resource = ('data/' + resource);
|
||||||
} else if (option.value === 'read-policies') {
|
} else if (option.value === 'read-policies') {
|
||||||
$('#selected-policy-action').text('read');
|
$('#selected-policy-action').text('read');
|
||||||
resource = ('policies/' + resource);
|
resource = ('policies/' + resource);
|
||||||
|
@ -380,7 +387,11 @@ nf.PolicyManagement = (function () {
|
||||||
var actionFormatter = function (row, cell, value, columnDef, dataContext) {
|
var actionFormatter = function (row, cell, value, columnDef, dataContext) {
|
||||||
var markup = '';
|
var markup = '';
|
||||||
|
|
||||||
markup += '<div title="Remove" class="pointer delete-user fa fa-trash"></div>';
|
// see if the user has permissions for the current policy
|
||||||
|
var currentEntity = $('#policy-table').data('policy');
|
||||||
|
if (currentEntity.permissions.canWrite === true) {
|
||||||
|
markup += '<div title="Remove" class="pointer delete-user fa fa-trash"></div>';
|
||||||
|
}
|
||||||
|
|
||||||
return markup;
|
return markup;
|
||||||
};
|
};
|
||||||
|
@ -538,7 +549,11 @@ nf.PolicyManagement = (function () {
|
||||||
dataType: 'json'
|
dataType: 'json'
|
||||||
}).done(function () {
|
}).done(function () {
|
||||||
loadPolicy();
|
loadPolicy();
|
||||||
}).fail(nf.Common.handleAjaxError);
|
}).fail(function (xhr, status, error) {
|
||||||
|
nf.Common.handleAjaxError(xhr, status, error);
|
||||||
|
resetPolicy();
|
||||||
|
loadPolicy();
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
nf.Dialog.showOkDialog({
|
nf.Dialog.showOkDialog({
|
||||||
headerText: 'Update Policy',
|
headerText: 'Update Policy',
|
||||||
|
@ -600,6 +615,7 @@ nf.PolicyManagement = (function () {
|
||||||
|
|
||||||
// re-sort and clear selection after updating
|
// re-sort and clear selection after updating
|
||||||
policyData.reSort();
|
policyData.reSort();
|
||||||
|
policyGrid.invalidate();
|
||||||
policyGrid.getSelectionModel().setSelectedRows([]);
|
policyGrid.getSelectionModel().setSelectedRows([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -635,19 +651,20 @@ nf.PolicyManagement = (function () {
|
||||||
// store the current policy version
|
// store the current policy version
|
||||||
$('#policy-table').data('policy', policyEntity);
|
$('#policy-table').data('policy', policyEntity);
|
||||||
|
|
||||||
// allow removal and modification as the policy is not inherited
|
// allow modification if allowed
|
||||||
$('#new-policy-user-button').prop('disabled', false);
|
$('#new-policy-user-button').prop('disabled', policyEntity.permissions.canWrite === false);
|
||||||
|
|
||||||
// see if the policy is for this resource
|
// see if the policy is for this resource
|
||||||
if (resourceAndAction.resource === policy.resource) {
|
if (resourceAndAction.resource === policy.resource) {
|
||||||
// allow remove when policy is not inherited
|
// allow remove when policy is not inherited
|
||||||
$('#delete-policy-button').prop('disabled', false);
|
$('#delete-policy-button').prop('disabled', policyEntity.permissions.canWrite === false);
|
||||||
} else {
|
} else {
|
||||||
$('#policy-message').text('Showing effective policy inherited from ' + convertToHumanReadableResource(policy.resource) + '. ');
|
$('#policy-message').text('Showing effective policy inherited from ' + convertToHumanReadableResource(policy.resource) + '. ');
|
||||||
$('#new-policy-message').hide();
|
|
||||||
|
// policy is inherited, we do not know if the user has permissions to modify the desired policy... show button and let server decide
|
||||||
$('#override-policy-message').show();
|
$('#override-policy-message').show();
|
||||||
|
|
||||||
// require non inherited policy for removal
|
// to not support policy deletion
|
||||||
$('#delete-policy-button').prop('disabled', true);
|
$('#delete-policy-button').prop('disabled', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,7 +677,6 @@ nf.PolicyManagement = (function () {
|
||||||
*/
|
*/
|
||||||
var loadPolicy = function () {
|
var loadPolicy = function () {
|
||||||
var resourceAndAction = getSelectedResourceAndAction();
|
var resourceAndAction = getSelectedResourceAndAction();
|
||||||
|
|
||||||
return $.Deferred(function (deferred) {
|
return $.Deferred(function (deferred) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
|
@ -673,7 +689,7 @@ nf.PolicyManagement = (function () {
|
||||||
$('#policy-last-refreshed').text(policyEntity.generated);
|
$('#policy-last-refreshed').text(policyEntity.generated);
|
||||||
|
|
||||||
// ensure appropriate actions for the loaded policy
|
// ensure appropriate actions for the loaded policy
|
||||||
if (policyEntity.permissions.canRead === true && policyEntity.permissions.canWrite === true) {
|
if (policyEntity.permissions.canRead === true) {
|
||||||
var policy = policyEntity.component;
|
var policy = policyEntity.component;
|
||||||
|
|
||||||
$('#policy-message').text(policy.resource);
|
$('#policy-message').text(policy.resource);
|
||||||
|
@ -684,9 +700,10 @@ nf.PolicyManagement = (function () {
|
||||||
// reset the policy
|
// reset the policy
|
||||||
resetPolicy();
|
resetPolicy();
|
||||||
|
|
||||||
// show an appropriate message
|
// since we cannot read, the policy may be inherited or not... we cannot tell
|
||||||
$('#policy-message').text('No policy for the specified resource and not authorized to access the inherited policy. ');
|
$('#policy-message').text('Not authorized to view the policy.');
|
||||||
$('#new-policy-message').hide();
|
|
||||||
|
// allow option to override because we don't know if it's supported or not
|
||||||
$('#override-policy-message').show();
|
$('#override-policy-message').show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,8 +715,9 @@ nf.PolicyManagement = (function () {
|
||||||
|
|
||||||
// show an appropriate message
|
// show an appropriate message
|
||||||
$('#policy-message').text('No policy for the specified resource.');
|
$('#policy-message').text('No policy for the specified resource.');
|
||||||
|
|
||||||
|
// we don't know if the user has permissions to the desired policy... show create button and allow the server to decide
|
||||||
$('#new-policy-message').show();
|
$('#new-policy-message').show();
|
||||||
$('#override-policy-message').hide();
|
|
||||||
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
} else if (xhr.status === 403) {
|
} else if (xhr.status === 403) {
|
||||||
|
@ -708,8 +726,6 @@ nf.PolicyManagement = (function () {
|
||||||
|
|
||||||
// show an appropriate message
|
// show an appropriate message
|
||||||
$('#policy-message').text('Not authorized to access the policy for the specified resource.');
|
$('#policy-message').text('Not authorized to access the policy for the specified resource.');
|
||||||
$('#new-policy-message').hide();
|
|
||||||
$('#override-policy-message').hide();
|
|
||||||
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
} else {
|
} else {
|
||||||
|
@ -747,7 +763,19 @@ nf.PolicyManagement = (function () {
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: 'application/json'
|
contentType: 'application/json'
|
||||||
}).done(function (policyEntity) {
|
}).done(function (policyEntity) {
|
||||||
populatePolicy(policyEntity);
|
// ensure appropriate actions for the loaded policy
|
||||||
|
if (policyEntity.permissions.canRead === true) {
|
||||||
|
var policy = policyEntity.component;
|
||||||
|
|
||||||
|
$('#policy-message').text(policy.resource);
|
||||||
|
|
||||||
|
// populate the policy details
|
||||||
|
populatePolicy(policyEntity);
|
||||||
|
} else {
|
||||||
|
// the request succeeded but we don't have access to the policy... reset/reload the policy
|
||||||
|
resetPolicy();
|
||||||
|
loadPolicy();
|
||||||
|
}
|
||||||
}).fail(nf.Common.handleAjaxError);
|
}).fail(nf.Common.handleAjaxError);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -792,7 +820,7 @@ nf.PolicyManagement = (function () {
|
||||||
contentType: 'application/json'
|
contentType: 'application/json'
|
||||||
}).done(function (policyEntity) {
|
}).done(function (policyEntity) {
|
||||||
// ensure appropriate actions for the loaded policy
|
// ensure appropriate actions for the loaded policy
|
||||||
if (policyEntity.permissions.canRead === true && policyEntity.permissions.canWrite === true) {
|
if (policyEntity.permissions.canRead === true) {
|
||||||
var policy = policyEntity.component;
|
var policy = policyEntity.component;
|
||||||
|
|
||||||
$('#policy-message').text(policy.resource);
|
$('#policy-message').text(policy.resource);
|
||||||
|
@ -800,15 +828,15 @@ nf.PolicyManagement = (function () {
|
||||||
// populate the policy details
|
// populate the policy details
|
||||||
populatePolicy(policyEntity);
|
populatePolicy(policyEntity);
|
||||||
} else {
|
} else {
|
||||||
// reset the policy
|
// the request succeeded but we don't have access to the policy... reset/reload the policy
|
||||||
resetPolicy();
|
resetPolicy();
|
||||||
|
loadPolicy();
|
||||||
// show an appropriate message
|
|
||||||
$('#policy-message').text('No policy for the specified resource and not authorized to access the inherited policy. ');
|
|
||||||
$('#new-policy-message').hide();
|
|
||||||
$('#override-policy-message').show();
|
|
||||||
}
|
}
|
||||||
}).fail(nf.Common.handleAjaxError);
|
}).fail(function (xhr, status, error) {
|
||||||
|
nf.Common.handleAjaxError(xhr, status, error)
|
||||||
|
resetPolicy();
|
||||||
|
loadPolicy();
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
nf.Dialog.showOkDialog({
|
nf.Dialog.showOkDialog({
|
||||||
headerText: 'Update Policy',
|
headerText: 'Update Policy',
|
||||||
|
@ -872,35 +900,6 @@ nf.PolicyManagement = (function () {
|
||||||
$('div.policy-selected-component-container').hide();
|
$('div.policy-selected-component-container').hide();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates the initial policy resource.
|
|
||||||
*
|
|
||||||
* @param resource
|
|
||||||
*/
|
|
||||||
var populateComponentResource = function (resource) {
|
|
||||||
// record the initial resource type
|
|
||||||
$('#selected-policy-component-type').text(resource);
|
|
||||||
|
|
||||||
var policyTarget = $('#component-policy-target').combo('getSelectedOption').value;
|
|
||||||
if (policyTarget === 'read-component') {
|
|
||||||
$('#selected-policy-action').text('read');
|
|
||||||
} else if (policyTarget === 'write-component') {
|
|
||||||
$('#selected-policy-action').text('write');
|
|
||||||
} else if (policyTarget === 'read-provenance-events') {
|
|
||||||
$('#selected-policy-action').text('read');
|
|
||||||
resource = ('provenance-events/' + resource);
|
|
||||||
} else if (policyTarget === 'read-policies') {
|
|
||||||
$('#selected-policy-action').text('read');
|
|
||||||
resource = ('policies/' + resource);
|
|
||||||
} else if (policyTarget === 'write-policies') {
|
|
||||||
$('#selected-policy-action').text('write');
|
|
||||||
resource = ('policies/' + resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the policy type
|
|
||||||
$('#selected-policy-type').text(resource);
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
* Initializes the settings page.
|
* Initializes the settings page.
|
||||||
|
@ -909,6 +908,13 @@ nf.PolicyManagement = (function () {
|
||||||
initAddTenantToPolicyDialog();
|
initAddTenantToPolicyDialog();
|
||||||
initPolicyTable();
|
initPolicyTable();
|
||||||
|
|
||||||
|
$('#policy-refresh-button').on('click', function () {
|
||||||
|
loadPolicy();
|
||||||
|
});
|
||||||
|
|
||||||
|
// reset the policy to initialize
|
||||||
|
resetPolicy();
|
||||||
|
|
||||||
// mark as initialized
|
// mark as initialized
|
||||||
initialized = true;
|
initialized = true;
|
||||||
},
|
},
|
||||||
|
@ -940,7 +946,7 @@ nf.PolicyManagement = (function () {
|
||||||
$('#global-policy-controls').hide();
|
$('#global-policy-controls').hide();
|
||||||
|
|
||||||
// update the visibility
|
// update the visibility
|
||||||
if (d.permissions.canRead) {
|
if (d.permissions.canRead === true) {
|
||||||
$('#policy-selected-controller-service-container div.policy-selected-component-name').text(d.component.name);
|
$('#policy-selected-controller-service-container div.policy-selected-component-name').text(d.component.name);
|
||||||
} else {
|
} else {
|
||||||
$('#policy-selected-controller-service-container div.policy-selected-component-name').text(d.id);
|
$('#policy-selected-controller-service-container div.policy-selected-component-name').text(d.id);
|
||||||
|
@ -949,7 +955,17 @@ nf.PolicyManagement = (function () {
|
||||||
|
|
||||||
// populate the initial resource
|
// populate the initial resource
|
||||||
$('#selected-policy-component-id').text(d.id);
|
$('#selected-policy-component-id').text(d.id);
|
||||||
populateComponentResource('controller-services');
|
$('#selected-policy-component-type').text('controller-services');
|
||||||
|
$('#component-policy-target')
|
||||||
|
.combo('setOptionEnabled', {
|
||||||
|
value: 'write-receive-data'
|
||||||
|
}, false)
|
||||||
|
.combo('setOptionEnabled', {
|
||||||
|
value: 'write-send-data'
|
||||||
|
}, false)
|
||||||
|
.combo('setSelectedOption', {
|
||||||
|
value: 'read-component'
|
||||||
|
});
|
||||||
|
|
||||||
return loadPolicy().always(showPolicy);
|
return loadPolicy().always(showPolicy);
|
||||||
},
|
},
|
||||||
|
@ -968,7 +984,7 @@ nf.PolicyManagement = (function () {
|
||||||
$('#global-policy-controls').hide();
|
$('#global-policy-controls').hide();
|
||||||
|
|
||||||
// update the visibility
|
// update the visibility
|
||||||
if (d.permissions.canRead) {
|
if (d.permissions.canRead === true) {
|
||||||
$('#policy-selected-reporting-task-container div.policy-selected-component-name').text(d.component.name);
|
$('#policy-selected-reporting-task-container div.policy-selected-component-name').text(d.component.name);
|
||||||
} else {
|
} else {
|
||||||
$('#policy-selected-reporting-task-container div.policy-selected-component-name').text(d.id);
|
$('#policy-selected-reporting-task-container div.policy-selected-component-name').text(d.id);
|
||||||
|
@ -977,7 +993,17 @@ nf.PolicyManagement = (function () {
|
||||||
|
|
||||||
// populate the initial resource
|
// populate the initial resource
|
||||||
$('#selected-policy-component-id').text(d.id);
|
$('#selected-policy-component-id').text(d.id);
|
||||||
populateComponentResource('reporting-tasks');
|
$('#selected-policy-component-type').text('reporting-tasks');
|
||||||
|
$('#component-policy-target')
|
||||||
|
.combo('setOptionEnabled', {
|
||||||
|
value: 'write-receive-data'
|
||||||
|
}, false)
|
||||||
|
.combo('setOptionEnabled', {
|
||||||
|
value: 'write-send-data'
|
||||||
|
}, false)
|
||||||
|
.combo('setSelectedOption', {
|
||||||
|
value: 'read-component'
|
||||||
|
});
|
||||||
|
|
||||||
return loadPolicy().always(showPolicy);
|
return loadPolicy().always(showPolicy);
|
||||||
},
|
},
|
||||||
|
@ -996,7 +1022,7 @@ nf.PolicyManagement = (function () {
|
||||||
$('#global-policy-controls').hide();
|
$('#global-policy-controls').hide();
|
||||||
|
|
||||||
// update the visibility
|
// update the visibility
|
||||||
if (d.permissions.canRead) {
|
if (d.permissions.canRead === true) {
|
||||||
$('#policy-selected-template-container div.policy-selected-component-name').text(d.template.name);
|
$('#policy-selected-template-container div.policy-selected-component-name').text(d.template.name);
|
||||||
} else {
|
} else {
|
||||||
$('#policy-selected-template-container div.policy-selected-component-name').text(d.id);
|
$('#policy-selected-template-container div.policy-selected-component-name').text(d.id);
|
||||||
|
@ -1005,7 +1031,17 @@ nf.PolicyManagement = (function () {
|
||||||
|
|
||||||
// populate the initial resource
|
// populate the initial resource
|
||||||
$('#selected-policy-component-id').text(d.id);
|
$('#selected-policy-component-id').text(d.id);
|
||||||
populateComponentResource('templates');
|
$('#selected-policy-component-type').text('templates');
|
||||||
|
$('#component-policy-target')
|
||||||
|
.combo('setOptionEnabled', {
|
||||||
|
value: 'write-receive-data'
|
||||||
|
}, false)
|
||||||
|
.combo('setOptionEnabled', {
|
||||||
|
value: 'write-send-data'
|
||||||
|
}, false)
|
||||||
|
.combo('setSelectedOption', {
|
||||||
|
value: 'read-component'
|
||||||
|
});
|
||||||
|
|
||||||
return loadPolicy().always(showPolicy);
|
return loadPolicy().always(showPolicy);
|
||||||
},
|
},
|
||||||
|
@ -1028,6 +1064,15 @@ nf.PolicyManagement = (function () {
|
||||||
if (selection.empty()) {
|
if (selection.empty()) {
|
||||||
$('#selected-policy-component-id').text(nf.Canvas.getGroupId());
|
$('#selected-policy-component-id').text(nf.Canvas.getGroupId());
|
||||||
resource = 'process-groups';
|
resource = 'process-groups';
|
||||||
|
|
||||||
|
// disable site to site option
|
||||||
|
$('#component-policy-target')
|
||||||
|
.combo('setOptionEnabled', {
|
||||||
|
value: 'write-receive-data'
|
||||||
|
}, false)
|
||||||
|
.combo('setOptionEnabled', {
|
||||||
|
value: 'write-send-data'
|
||||||
|
}, false);
|
||||||
} else {
|
} else {
|
||||||
var d = selection.datum();
|
var d = selection.datum();
|
||||||
$('#selected-policy-component-id').text(d.id);
|
$('#selected-policy-component-id').text(d.id);
|
||||||
|
@ -1059,7 +1104,10 @@ nf.PolicyManagement = (function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// populate the initial resource
|
// populate the initial resource
|
||||||
populateComponentResource(resource);
|
$('#selected-policy-component-type').text(resource);
|
||||||
|
$('#component-policy-target').combo('setSelectedOption', {
|
||||||
|
value: 'read-component'
|
||||||
|
});
|
||||||
|
|
||||||
return loadPolicy().always(showPolicy);
|
return loadPolicy().always(showPolicy);
|
||||||
},
|
},
|
||||||
|
|
|
@ -411,7 +411,7 @@ public class PersistentProvenanceRepository implements ProvenanceRepository {
|
||||||
|
|
||||||
final Authorizable eventAuthorizable;
|
final Authorizable eventAuthorizable;
|
||||||
try {
|
try {
|
||||||
eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
|
eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
|
||||||
} catch (final ResourceNotFoundException rnfe) {
|
} catch (final ResourceNotFoundException rnfe) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -425,7 +425,7 @@ public class PersistentProvenanceRepository implements ProvenanceRepository {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Authorizable eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
|
final Authorizable eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
|
||||||
eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
|
eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,7 +243,7 @@ public class VolatileProvenanceRepository implements ProvenanceRepository {
|
||||||
|
|
||||||
final Authorizable eventAuthorizable;
|
final Authorizable eventAuthorizable;
|
||||||
try {
|
try {
|
||||||
eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
|
eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
|
||||||
} catch (final ResourceNotFoundException rnfe) {
|
} catch (final ResourceNotFoundException rnfe) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ public class VolatileProvenanceRepository implements ProvenanceRepository {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Authorizable eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
|
final Authorizable eventAuthorizable = resourceFactory.createDataAuthorizable(event.getComponentId());
|
||||||
eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
|
eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue