mirror of https://github.com/apache/nifi.git
NIFI-2695: - Providing more granular and meaningful authorization error messages.
This closes #1309. Signed-off-by: Bryan Bende <bbende@apache.org>
This commit is contained in:
parent
41189b055f
commit
b1c9f0e764
|
@ -158,8 +158,7 @@ public abstract class AbstractPolicyBasedAuthorizer implements Authorizer {
|
|||
return AuthorizationResult.approved();
|
||||
}
|
||||
|
||||
|
||||
return AuthorizationResult.denied();
|
||||
return AuthorizationResult.denied(request.getExplanationSupplier().get());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,12 +20,15 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Represents an authorization request for a given user/entity performing an action against a resource within some userContext.
|
||||
*/
|
||||
public class AuthorizationRequest {
|
||||
|
||||
public static final String DEFAULT_EXPLANATION = "Unable to perform the desired action.";
|
||||
|
||||
private final Resource resource;
|
||||
private final String identity;
|
||||
private final RequestAction action;
|
||||
|
@ -33,6 +36,7 @@ public class AuthorizationRequest {
|
|||
private final boolean isAnonymous;
|
||||
private final Map<String, String> userContext;
|
||||
private final Map<String, String> resourceContext;
|
||||
private final Supplier<String> explanationSupplier;
|
||||
|
||||
private AuthorizationRequest(final Builder builder) {
|
||||
Objects.requireNonNull(builder.resource, "The resource is required when creating an authorization request");
|
||||
|
@ -47,6 +51,16 @@ public class AuthorizationRequest {
|
|||
this.isAnonymous = builder.isAnonymous;
|
||||
this.userContext = builder.userContext == null ? null : Collections.unmodifiableMap(builder.userContext);
|
||||
this.resourceContext = builder.resourceContext == null ? null : Collections.unmodifiableMap(builder.resourceContext);
|
||||
this.explanationSupplier = () -> {
|
||||
final String explanation = builder.explanationSupplier.get();
|
||||
|
||||
// ensure the specified supplier returns non null
|
||||
if (explanation == null) {
|
||||
return DEFAULT_EXPLANATION;
|
||||
} else {
|
||||
return explanation;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,6 +126,15 @@ public class AuthorizationRequest {
|
|||
return resourceContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* A supplier for the explanation if access is denied. Non null.
|
||||
*
|
||||
* @return The explanation supplier if access is denied
|
||||
*/
|
||||
public Supplier<String> getExplanationSupplier() {
|
||||
return explanationSupplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* AuthorizationRequest builder.
|
||||
*/
|
||||
|
@ -124,6 +147,7 @@ public class AuthorizationRequest {
|
|||
private RequestAction action;
|
||||
private Map<String, String> userContext;
|
||||
private Map<String, String> resourceContext;
|
||||
private Supplier<String> explanationSupplier = () -> DEFAULT_EXPLANATION;
|
||||
|
||||
public Builder resource(final Resource resource) {
|
||||
this.resource = resource;
|
||||
|
@ -164,6 +188,13 @@ public class AuthorizationRequest {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder explanationSupplier(final Supplier<String> explanationSupplier) {
|
||||
if (explanationSupplier != null) {
|
||||
this.explanationSupplier = explanationSupplier;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthorizationRequest build() {
|
||||
return new AuthorizationRequest(this);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public class AuthorizationResult {
|
|||
}
|
||||
|
||||
private static final AuthorizationResult APPROVED = new AuthorizationResult(Result.Approved, null);
|
||||
private static final AuthorizationResult RESOURCE_NOT_FOUND = new AuthorizationResult(Result.ResourceNotFound, null);
|
||||
private static final AuthorizationResult RESOURCE_NOT_FOUND = new AuthorizationResult(Result.ResourceNotFound, "Not authorized for the requested resource.");
|
||||
|
||||
private final Result result;
|
||||
private final String explanation;
|
||||
|
@ -44,6 +44,10 @@ public class AuthorizationResult {
|
|||
throw new IllegalArgumentException("An explanation is required when the authorization request is denied.");
|
||||
}
|
||||
|
||||
if (Result.ResourceNotFound.equals(result) && explanation == null) {
|
||||
throw new IllegalArgumentException("An explanation is required when the authorization request is resource not found.");
|
||||
}
|
||||
|
||||
this.result = result;
|
||||
this.explanation = explanation;
|
||||
}
|
||||
|
@ -83,7 +87,7 @@ public class AuthorizationResult {
|
|||
* @return a new denied AuthorizationResult
|
||||
*/
|
||||
public static AuthorizationResult denied() {
|
||||
return denied("Access is denied");
|
||||
return denied(AuthorizationRequest.DEFAULT_EXPLANATION);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,4 +34,11 @@ public interface Resource {
|
|||
* @return name of this resource
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* The description of this resource that may be safely used in messages to the client.
|
||||
*
|
||||
* @return safe description
|
||||
*/
|
||||
String getSafeDescription();
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ import org.apache.nifi.authorization.Resource;
|
|||
import org.apache.nifi.authorization.UserContextKeys;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public interface Authorizable {
|
||||
|
||||
|
@ -70,7 +70,7 @@ public interface Authorizable {
|
|||
*/
|
||||
default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
|
||||
if (user == null) {
|
||||
return AuthorizationResult.denied("Unknown user");
|
||||
return AuthorizationResult.denied("Unknown user.");
|
||||
}
|
||||
|
||||
final Map<String,String> userContext;
|
||||
|
@ -81,15 +81,28 @@ public interface Authorizable {
|
|||
userContext = null;
|
||||
}
|
||||
|
||||
// build the request
|
||||
final Resource resource = getResource();
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.identity(user.getIdentity())
|
||||
.anonymous(user.isAnonymous())
|
||||
.accessAttempt(false)
|
||||
.action(action)
|
||||
.resource(getResource())
|
||||
.resource(resource)
|
||||
.resourceContext(resourceContext)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> {
|
||||
// build the safe explanation
|
||||
final StringBuilder safeDescription = new StringBuilder("Unable to ");
|
||||
|
||||
if (RequestAction.READ.equals(action)) {
|
||||
safeDescription.append("view ");
|
||||
} else {
|
||||
safeDescription.append("modify ");
|
||||
}
|
||||
safeDescription.append(resource.getSafeDescription()).append(".");
|
||||
|
||||
return safeDescription.toString();
|
||||
})
|
||||
.build();
|
||||
|
||||
// perform the authorization
|
||||
|
@ -99,9 +112,37 @@ public interface Authorizable {
|
|||
if (Result.ResourceNotFound.equals(result.getResult())) {
|
||||
final Authorizable parent = getParentAuthorizable();
|
||||
if (parent == null) {
|
||||
return AuthorizationResult.denied();
|
||||
return AuthorizationResult.denied("No applicable policies could be found.");
|
||||
} else {
|
||||
return parent.checkAuthorization(authorizer, action, user, resourceContext);
|
||||
// create a custom authorizable to override the safe description but still defer to the parent authorizable
|
||||
final Authorizable parentProxy = new Authorizable() {
|
||||
@Override
|
||||
public Authorizable getParentAuthorizable() {
|
||||
return parent.getParentAuthorizable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getResource() {
|
||||
final Resource parentResource = parent.getResource();
|
||||
return new Resource() {
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return parentResource.getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parentResource.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return resource.getSafeDescription();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
return parentProxy.checkAuthorization(authorizer, action, user, resourceContext);
|
||||
}
|
||||
} else {
|
||||
return result;
|
||||
|
@ -133,7 +174,7 @@ public interface Authorizable {
|
|||
*/
|
||||
default void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Unknown user");
|
||||
throw new AccessDeniedException("Unknown user.");
|
||||
}
|
||||
|
||||
final Map<String,String> userContext;
|
||||
|
@ -144,23 +185,65 @@ public interface Authorizable {
|
|||
userContext = null;
|
||||
}
|
||||
|
||||
final Resource resource = getResource();
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.identity(user.getIdentity())
|
||||
.anonymous(user.isAnonymous())
|
||||
.accessAttempt(true)
|
||||
.action(action)
|
||||
.resource(getResource())
|
||||
.resource(resource)
|
||||
.resourceContext(resourceContext)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> {
|
||||
// build the safe explanation
|
||||
final StringBuilder safeDescription = new StringBuilder("Unable to ");
|
||||
|
||||
if (RequestAction.READ.equals(action)) {
|
||||
safeDescription.append("view ");
|
||||
} else {
|
||||
safeDescription.append("modify ");
|
||||
}
|
||||
safeDescription.append(resource.getSafeDescription()).append(".");
|
||||
|
||||
return safeDescription.toString();
|
||||
})
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (Result.ResourceNotFound.equals(result.getResult())) {
|
||||
final Authorizable parent = getParentAuthorizable();
|
||||
if (parent == null) {
|
||||
throw new AccessDeniedException("Access is denied");
|
||||
throw new AccessDeniedException("No applicable policies could be found.");
|
||||
} else {
|
||||
parent.authorize(authorizer, action, user, resourceContext);
|
||||
// create a custom authorizable to override the safe description but still defer to the parent authorizable
|
||||
final Authorizable parentProxy = new Authorizable() {
|
||||
@Override
|
||||
public Authorizable getParentAuthorizable() {
|
||||
return parent.getParentAuthorizable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getResource() {
|
||||
final Resource parentResource = parent.getResource();
|
||||
return new Resource() {
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return parentResource.getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parentResource.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return resource.getSafeDescription();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
parentProxy.authorize(authorizer, action, user, resourceContext);
|
||||
}
|
||||
} else if (Result.Denied.equals(result.getResult())) {
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.authorization;
|
||||
|
||||
import org.apache.nifi.authorization.MockPolicyBasedAuthorizer;
|
||||
import org.apache.nifi.authorization.exception.AuthorizerCreationException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -42,6 +41,11 @@ public class TestAbstractPolicyBasedAuthorizer {
|
|||
public String getName() {
|
||||
return "resource1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "description1";
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
|
|
|
@ -447,8 +447,12 @@ public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
|
|||
|
||||
// convert any access controls on ports to the appropriate policies
|
||||
for (PortDTO portDTO : ports) {
|
||||
final boolean isInputPort = portDTO.getType() != null && portDTO.getType().equals("inputPort");
|
||||
final Resource resource = ResourceFactory.getDataTransferResource(isInputPort, portDTO.getId(), portDTO.getName());
|
||||
final Resource resource;
|
||||
if (portDTO.getType() != null && portDTO.getType().equals("inputPort")) {
|
||||
resource = ResourceFactory.getDataTransferResource(ResourceFactory.getComponentResource(ResourceType.InputPort, portDTO.getId(), portDTO.getName()));
|
||||
} else {
|
||||
resource = ResourceFactory.getDataTransferResource(ResourceFactory.getComponentResource(ResourceType.OutputPort, portDTO.getId(), portDTO.getName()));
|
||||
}
|
||||
|
||||
if (portDTO.getUserAccessControl() != null) {
|
||||
for (String userAccessControl : portDTO.getUserAccessControl()) {
|
||||
|
|
|
@ -358,7 +358,8 @@ public class FileAuthorizerTest {
|
|||
assertEquals(2, user6Policies.get(ResourceType.SiteToSite.getValue()).size());
|
||||
assertTrue(user6Policies.get(ResourceType.SiteToSite.getValue()).contains(RequestAction.WRITE));
|
||||
|
||||
final Resource inputPortResource = ResourceFactory.getDataTransferResource(true, "2f7d1606-b090-4be7-a592-a5b70fb55531", "TCP Input");
|
||||
final Resource inputPortResource = ResourceFactory.getDataTransferResource(
|
||||
ResourceFactory.getComponentResource(ResourceType.InputPort, "2f7d1606-b090-4be7-a592-a5b70fb55531", "TCP Input"));
|
||||
final AccessPolicy inputPortPolicy = authorizer.getUsersAndAccessPolicies().getAccessPolicy(inputPortResource.getIdentifier(), RequestAction.WRITE);
|
||||
assertNotNull(inputPortPolicy);
|
||||
assertEquals(1, inputPortPolicy.getUsers().size());
|
||||
|
@ -366,7 +367,8 @@ public class FileAuthorizerTest {
|
|||
assertEquals(1, inputPortPolicy.getGroups().size());
|
||||
assertTrue(inputPortPolicy.getGroups().contains(group1.getIdentifier()));
|
||||
|
||||
final Resource outputPortResource = ResourceFactory.getDataTransferResource(false, "2f7d1606-b090-4be7-a592-a5b70fb55532", "TCP Output");
|
||||
final Resource outputPortResource = ResourceFactory.getDataTransferResource(
|
||||
ResourceFactory.getComponentResource(ResourceType.OutputPort, "2f7d1606-b090-4be7-a592-a5b70fb55532", "TCP Output"));
|
||||
final AccessPolicy outputPortPolicy = authorizer.getUsersAndAccessPolicies().getAccessPolicy(outputPortResource.getIdentifier(), RequestAction.WRITE);
|
||||
assertNotNull(outputPortPolicy);
|
||||
assertEquals(1, outputPortPolicy.getUsers().size());
|
||||
|
@ -432,7 +434,8 @@ public class FileAuthorizerTest {
|
|||
final Group group1 = groups.iterator().next();
|
||||
assertEquals("group1", group1.getName());
|
||||
|
||||
final Resource inputPortResource = ResourceFactory.getDataTransferResource(true, "2f7d1606-b090-4be7-a592-a5b70fb55531", "TCP Input");
|
||||
final Resource inputPortResource = ResourceFactory.getDataTransferResource(
|
||||
ResourceFactory.getComponentResource(ResourceType.InputPort, "2f7d1606-b090-4be7-a592-a5b70fb55531", "TCP Input"));
|
||||
final AccessPolicy inputPortPolicy = authorizer.getUsersAndAccessPolicies().getAccessPolicy(inputPortResource.getIdentifier(), RequestAction.WRITE);
|
||||
assertNotNull(inputPortPolicy);
|
||||
assertEquals(1, inputPortPolicy.getUsers().size());
|
||||
|
@ -440,7 +443,8 @@ public class FileAuthorizerTest {
|
|||
assertEquals(1, inputPortPolicy.getGroups().size());
|
||||
assertTrue(inputPortPolicy.getGroups().contains(group1.getIdentifier()));
|
||||
|
||||
final Resource outputPortResource = ResourceFactory.getDataTransferResource(false, "2f7d1606-b090-4be7-a592-a5b70fb55532", "TCP Output");
|
||||
final Resource outputPortResource = ResourceFactory.getDataTransferResource(
|
||||
ResourceFactory.getComponentResource(ResourceType.OutputPort, "2f7d1606-b090-4be7-a592-a5b70fb55532", "TCP Output"));
|
||||
final AccessPolicy outputPortPolicy = authorizer.getUsersAndAccessPolicies().getAccessPolicy(outputPortResource.getIdentifier(), RequestAction.WRITE);
|
||||
assertNotNull(outputPortPolicy);
|
||||
assertEquals(1, outputPortPolicy.getUsers().size());
|
||||
|
|
|
@ -89,7 +89,7 @@ public class AccessPolicyAuthorizable implements Authorizable, EnforcePolicyPerm
|
|||
@Override
|
||||
public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Unknown user");
|
||||
throw new AccessDeniedException("Unknown user.");
|
||||
}
|
||||
|
||||
final AuthorizationResult resourceResult = Authorizable.super.checkAuthorization(authorizer, action, user, resourceContext);
|
||||
|
@ -105,7 +105,7 @@ public class AccessPolicyAuthorizable implements Authorizable, EnforcePolicyPerm
|
|||
@Override
|
||||
public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Unknown user");
|
||||
throw new AccessDeniedException("Unknown user.");
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -62,7 +62,7 @@ public class DataAuthorizable implements Authorizable, EnforcePolicyPermissionsT
|
|||
@Override
|
||||
public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
|
||||
if (user == null) {
|
||||
return AuthorizationResult.denied("Unknown user");
|
||||
return AuthorizationResult.denied("Unknown user.");
|
||||
}
|
||||
|
||||
AuthorizationResult result = null;
|
||||
|
@ -100,7 +100,7 @@ public class DataAuthorizable implements Authorizable, EnforcePolicyPermissionsT
|
|||
@Override
|
||||
public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Unknown user");
|
||||
throw new AccessDeniedException("Unknown user.");
|
||||
}
|
||||
|
||||
// calculate the dn chain
|
||||
|
|
|
@ -32,6 +32,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "Controller";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "the controller";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource FLOW_RESOURCE = new Resource() {
|
||||
|
@ -44,6 +49,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "NiFi Flow";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "the user interface";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource POLICY_RESOURCE = new Resource() {
|
||||
|
@ -54,7 +64,12 @@ public final class ResourceFactory {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Policy";
|
||||
return "Policies for ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "the policies for ";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -68,6 +83,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "Counters";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "counters";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource PROVENANCE_RESOURCE = new Resource() {
|
||||
|
@ -80,6 +100,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "Provenance";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "provenance";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource DATA_RESOURCE = new Resource() {
|
||||
|
@ -90,7 +115,12 @@ public final class ResourceFactory {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Data";
|
||||
return "Data for ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "the data for ";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -104,6 +134,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "Proxy User Requests";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "proxy requests on behalf of users";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource RESOURCE_RESOURCE = new Resource() {
|
||||
|
@ -116,6 +151,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "NiFi Resources";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "resources";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource SITE_TO_SITE_RESOURCE = new Resource() {
|
||||
|
@ -128,6 +168,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "Site to Site";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "site-to-site details";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource SYSTEM_RESOURCE = new Resource() {
|
||||
|
@ -140,6 +185,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "System";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "system diagnostics";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource RESTRICTED_COMPONENTS_RESOURCE = new Resource() {
|
||||
|
@ -152,6 +202,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "Restricted Components";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "restricted components";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource TENANT_RESOURCE = new Resource() {
|
||||
|
@ -164,6 +219,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "Tenant";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "users/user groups";
|
||||
}
|
||||
};
|
||||
|
||||
private final static Resource POLICIES_RESOURCE = new Resource() {
|
||||
|
@ -177,6 +237,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "Access Policies";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "policies";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -271,30 +336,6 @@ public final class ResourceFactory {
|
|||
return TENANT_RESOURCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Resource for performing transferring data to a port.
|
||||
*
|
||||
* @param isInputPort Whether this port is an input port or an output port
|
||||
* @param identifier The identifier of the component being accessed
|
||||
* @param name The name of the component being accessed
|
||||
* @return The resource
|
||||
*/
|
||||
public static Resource getDataTransferResource(final boolean isInputPort, final String identifier, final String name) {
|
||||
Objects.requireNonNull(identifier, "The component identifier must be specified.");
|
||||
|
||||
return new Resource() {
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return String.format("%s/%s/%s", ResourceType.DataTransfer.getValue(), isInputPort ? "input-ports" : "output-ports", identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Resource for performing transferring data to a port.
|
||||
*
|
||||
|
@ -314,6 +355,11 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return "Transfer data to " + resource.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "data transfers to " + resource.getSafeDescription();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -342,7 +388,12 @@ public final class ResourceFactory {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Policies for " + resource.getName();
|
||||
return POLICY_RESOURCE.getName() + resource.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return POLICY_RESOURCE.getSafeDescription() + resource.getSafeDescription();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -369,6 +420,47 @@ public final class ResourceFactory {
|
|||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
final String componentType;
|
||||
switch (resourceType) {
|
||||
case ControllerService:
|
||||
componentType = "Controller Service";
|
||||
break;
|
||||
case ProcessGroup:
|
||||
componentType = "Process Group";
|
||||
break;
|
||||
case Template:
|
||||
componentType = "Template";
|
||||
break;
|
||||
case Funnel:
|
||||
componentType = "Funnel";
|
||||
break;
|
||||
case InputPort:
|
||||
componentType = "Input Port";
|
||||
break;
|
||||
case OutputPort:
|
||||
componentType = "Output Port";
|
||||
break;
|
||||
case Processor:
|
||||
componentType = "Processor";
|
||||
break;
|
||||
case RemoteProcessGroup:
|
||||
componentType = "Remote Process Group";
|
||||
break;
|
||||
case ReportingTask:
|
||||
componentType = "Reporting Task";
|
||||
break;
|
||||
case Label:
|
||||
componentType = "Label";
|
||||
break;
|
||||
default:
|
||||
componentType = "Component";
|
||||
break;
|
||||
}
|
||||
return componentType + " with ID " + identifier;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -387,7 +479,12 @@ public final class ResourceFactory {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Data for " + resource.getName();
|
||||
return DATA_RESOURCE.getName() + resource.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return DATA_RESOURCE.getSafeDescription() + resource.getSafeDescription();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -136,6 +136,11 @@ public final class StandardConnection implements Connection {
|
|||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "Connection " + StandardConnection.this.getIdentifier();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -172,7 +177,7 @@ public final class StandardConnection implements Connection {
|
|||
@Override
|
||||
public AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
|
||||
if (user == null) {
|
||||
return AuthorizationResult.denied("Unknown user");
|
||||
return AuthorizationResult.denied("Unknown user.");
|
||||
}
|
||||
|
||||
// check the source
|
||||
|
@ -188,7 +193,7 @@ public final class StandardConnection implements Connection {
|
|||
@Override
|
||||
public void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Unknown user");
|
||||
throw new AccessDeniedException("Unknown user.");
|
||||
}
|
||||
|
||||
getSourceAuthorizable().authorize(authorizer, action, user, resourceContext);
|
||||
|
|
|
@ -963,6 +963,11 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
public String getName() {
|
||||
return resourceIdentifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "User " + userId;
|
||||
}
|
||||
},
|
||||
() -> userDAO.deleteUser(userId),
|
||||
false, // no user specific policies to remove
|
||||
|
@ -993,6 +998,11 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
public String getName() {
|
||||
return resourceIdentifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "User Group " + userGroupId;
|
||||
}
|
||||
},
|
||||
() -> userGroupDAO.deleteUserGroup(userGroupId),
|
||||
false, // no user group specific policies to remove
|
||||
|
@ -1020,6 +1030,11 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
public String getName() {
|
||||
return accessPolicy.getResource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "Policy " + accessPolicyId;
|
||||
}
|
||||
},
|
||||
() -> accessPolicyDAO.deleteAccessPolicy(accessPolicyId),
|
||||
false, // no need to clean up any policies as it's already been removed above
|
||||
|
@ -2514,6 +2529,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
.accessAttempt(false)
|
||||
.action(RequestAction.WRITE)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> "Unable to retrieve port details.")
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
|
@ -2680,6 +2696,11 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
public String getName() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "Policy " + resource;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -3100,7 +3121,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
return entityFactory.createStatusHistoryEntity(dto, permissions);
|
||||
}
|
||||
|
||||
private boolean authorizeAction(final Action action) {
|
||||
private AuthorizationResult authorizeAction(final Action action) {
|
||||
final String sourceId = action.getSourceId();
|
||||
final Component type = action.getSourceType();
|
||||
|
||||
|
@ -3149,12 +3170,11 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
}
|
||||
} catch (final ResourceNotFoundException e) {
|
||||
// if the underlying component is gone, disallow
|
||||
return false;
|
||||
return AuthorizationResult.denied("The component of this action is no longer in the data flow.");
|
||||
}
|
||||
|
||||
// perform the authorization
|
||||
final AuthorizationResult result = authorizable.checkAuthorization(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
|
||||
return Result.Approved.equals(result.getResult());
|
||||
return authorizable.checkAuthorization(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3178,7 +3198,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
if (history.getActions() != null) {
|
||||
final List<ActionEntity> actionEntities = new ArrayList<>();
|
||||
for (final Action action : history.getActions()) {
|
||||
actionEntities.add(entityFactory.createActionEntity(dtoFactory.createActionDto(action), authorizeAction(action)));
|
||||
final AuthorizationResult result = authorizeAction(action);
|
||||
actionEntities.add(entityFactory.createActionEntity(dtoFactory.createActionDto(action), Result.Approved.equals(result.getResult())));
|
||||
}
|
||||
historyDto.setActions(actionEntities);
|
||||
}
|
||||
|
@ -3197,9 +3218,10 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
throw new ResourceNotFoundException(String.format("Unable to find action with id '%s'.", actionId));
|
||||
}
|
||||
|
||||
final boolean authorized = authorizeAction(action);
|
||||
final AuthorizationResult result = authorizeAction(action);
|
||||
final boolean authorized = Result.Approved.equals(result.getResult());
|
||||
if (!authorized) {
|
||||
throw new AccessDeniedException("Access is denied.");
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
}
|
||||
|
||||
// return the action
|
||||
|
|
|
@ -115,12 +115,12 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
.accessAttempt(true)
|
||||
.action(RequestAction.READ)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> "Unable to view the user interface.")
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (!Result.Approved.equals(result.getResult())) {
|
||||
final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied";
|
||||
throw new AccessDeniedException(message);
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -252,7 +252,7 @@ public class AccessResource extends ApplicationResource {
|
|||
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Unable to determine user details.");
|
||||
throw new AccessDeniedException("No user authenticated in the request.");
|
||||
}
|
||||
|
||||
final OtpAuthenticationToken authenticationToken = new OtpAuthenticationToken(user.getIdentity());
|
||||
|
@ -297,7 +297,7 @@ public class AccessResource extends ApplicationResource {
|
|||
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Unable to determine user details.");
|
||||
throw new AccessDeniedException("No user authenticated in the request.");
|
||||
}
|
||||
|
||||
final OtpAuthenticationToken authenticationToken = new OtpAuthenticationToken(user.getIdentity());
|
||||
|
|
|
@ -112,12 +112,23 @@ public class ControllerResource extends ApplicationResource {
|
|||
.accessAttempt(true)
|
||||
.action(action)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> {
|
||||
final StringBuilder explanation = new StringBuilder("Unable to ");
|
||||
|
||||
if (RequestAction.READ.equals(action)) {
|
||||
explanation.append("view ");
|
||||
} else {
|
||||
explanation.append("modify ");
|
||||
}
|
||||
explanation.append("the controller.");
|
||||
|
||||
return explanation.toString();
|
||||
})
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (!Result.Approved.equals(result.getResult())) {
|
||||
final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied";
|
||||
throw new AccessDeniedException(message);
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,12 +98,23 @@ public class CountersResource extends ApplicationResource {
|
|||
.accessAttempt(true)
|
||||
.action(action)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> {
|
||||
final StringBuilder explanation = new StringBuilder("Unable to ");
|
||||
|
||||
if (RequestAction.READ.equals(action)) {
|
||||
explanation.append("view ");
|
||||
} else {
|
||||
explanation.append("modify ");
|
||||
}
|
||||
explanation.append("counters.");
|
||||
|
||||
return explanation.toString();
|
||||
})
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (!Result.Approved.equals(result.getResult())) {
|
||||
final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied";
|
||||
throw new AccessDeniedException(message);
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -218,12 +218,12 @@ public class FlowResource extends ApplicationResource {
|
|||
.accessAttempt(true)
|
||||
.action(RequestAction.READ)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> "Unable to view the user interface.")
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (!Result.Approved.equals(result.getResult())) {
|
||||
final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied";
|
||||
throw new AccessDeniedException(message);
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,12 +108,12 @@ public class ProvenanceResource extends ApplicationResource {
|
|||
.accessAttempt(true)
|
||||
.action(RequestAction.READ)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> "Unable to query provenance.")
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (!Result.Approved.equals(result.getResult())) {
|
||||
final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied";
|
||||
throw new AccessDeniedException(message);
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,12 +78,12 @@ public class ResourceResource extends ApplicationResource {
|
|||
.accessAttempt(true)
|
||||
.action(RequestAction.READ)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> "Unable to retrieve resources.")
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (!Result.Approved.equals(result.getResult())) {
|
||||
final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied";
|
||||
throw new AccessDeniedException(message);
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -116,12 +116,12 @@ public class SiteToSiteResource extends ApplicationResource {
|
|||
.accessAttempt(true)
|
||||
.action(RequestAction.READ)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> "Unable to retrieve site to site details.")
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (!Result.Approved.equals(result.getResult())) {
|
||||
final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied";
|
||||
throw new AccessDeniedException(message);
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,12 +81,12 @@ public class SystemDiagnosticsResource extends ApplicationResource {
|
|||
.accessAttempt(true)
|
||||
.action(RequestAction.READ)
|
||||
.userContext(userContext)
|
||||
.explanationSupplier(() -> "Unable to view system diagnostics.")
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (!Result.Approved.equals(result.getResult())) {
|
||||
final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied";
|
||||
throw new AccessDeniedException(message);
|
||||
throw new AccessDeniedException(result.getExplanation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,13 +58,16 @@ public class AccessDeniedExceptionMapper implements ExceptionMapper<AccessDenied
|
|||
identity = user.getIdentity();
|
||||
}
|
||||
|
||||
logger.info(String.format("%s does not have permission to access the requested resource. Returning %s response.", identity, status));
|
||||
logger.info(String.format("%s does not have permission to access the requested resource. %s Returning %s response.", identity, exception.getMessage(), status));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(StringUtils.EMPTY, exception);
|
||||
}
|
||||
|
||||
return Response.status(status).entity("Unable to perform the desired action due to insufficient permissions. Contact the system administrator.").type("text/plain").build();
|
||||
return Response.status(status)
|
||||
.entity(String.format("%s Contact the system administrator.", exception.getMessage()))
|
||||
.type("text/plain")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1241,7 +1241,7 @@ public class ControllerFacade implements Authorizable {
|
|||
private AuthorizationResult checkAuthorizationForReplay(final ProvenanceEventRecord event) {
|
||||
// if the connection id isn't specified, then the replay wouldn't be available anyways and we have nothing to authorize against so deny it`
|
||||
if (event.getSourceQueueIdentifier() == null) {
|
||||
return AuthorizationResult.denied();
|
||||
return AuthorizationResult.denied("The connection id in the provenance event is unknown.");
|
||||
}
|
||||
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
|
@ -1272,7 +1272,7 @@ public class ControllerFacade implements Authorizable {
|
|||
private void authorizeReplay(final ProvenanceEventRecord event) {
|
||||
// if the connection id isn't specified, then the replay wouldn't be available anyways and we have nothing to authorize against so deny it`
|
||||
if (event.getSourceQueueIdentifier() == null) {
|
||||
throw new AccessDeniedException("The connection id is unknown.");
|
||||
throw new AccessDeniedException("The connection id in the provenance event is unknown.");
|
||||
}
|
||||
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
|
|
|
@ -514,7 +514,7 @@ nf.Common = (function () {
|
|||
if (xhr.status === 401) {
|
||||
$('#message-title').text('Unauthorized');
|
||||
} else if (xhr.status === 403) {
|
||||
$('#message-title').text('Access Denied');
|
||||
$('#message-title').text('Insufficient Permissions');
|
||||
} else if (xhr.status === 409) {
|
||||
$('#message-title').text('Invalid State');
|
||||
} else {
|
||||
|
@ -535,12 +535,17 @@ nf.Common = (function () {
|
|||
return;
|
||||
}
|
||||
|
||||
// status code 400, 403, 404, and 409 are expected response codes for common errors.
|
||||
if (xhr.status === 400 || xhr.status === 403 || xhr.status === 404 || xhr.status === 409 || xhr.status === 503) {
|
||||
// status code 400, 404, and 409 are expected response codes for common errors.
|
||||
if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409 || xhr.status === 503) {
|
||||
nf.Dialog.showOkDialog({
|
||||
headerText: 'Error',
|
||||
dialogContent: nf.Common.escapeHtml(xhr.responseText)
|
||||
});
|
||||
} else if (xhr.status === 403) {
|
||||
nf.Dialog.showOkDialog({
|
||||
headerText: 'Insufficient Permissions',
|
||||
dialogContent: nf.Common.escapeHtml(xhr.responseText)
|
||||
});
|
||||
} else {
|
||||
if (xhr.status < 99 || xhr.status === 12007 || xhr.status === 12029) {
|
||||
var content = 'Please ensure the application is running and check the logs for any errors.';
|
||||
|
|
|
@ -2384,14 +2384,14 @@ public class PersistentProvenanceRepository implements ProvenanceRepository {
|
|||
}
|
||||
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Lineage Submission because no user id was provided");
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Lineage Submission because no user id was provided in the lineage request.");
|
||||
}
|
||||
|
||||
if (userId == null || userId.equals(user.getIdentity())) {
|
||||
return submission;
|
||||
}
|
||||
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Lineage Submission because " + user.getIdentity() + " is not the user who submitted the request");
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Lineage Submission because " + user.getIdentity() + " is not the user who submitted the request.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2405,14 +2405,14 @@ public class PersistentProvenanceRepository implements ProvenanceRepository {
|
|||
}
|
||||
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because no user id was provided");
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because no user id was provided in the provenance request.");
|
||||
}
|
||||
|
||||
if (userId == null || userId.equals(user.getIdentity())) {
|
||||
return submission;
|
||||
}
|
||||
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because " + user.getIdentity() + " is not the user who submitted the request");
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because " + user.getIdentity() + " is not the user who submitted the request.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -460,14 +460,14 @@ public class VolatileProvenanceRepository implements ProvenanceRepository {
|
|||
}
|
||||
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because no user id was provided");
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because no user id was provided in the provenance request.");
|
||||
}
|
||||
|
||||
if (userId == null || userId.equals(user.getIdentity())) {
|
||||
return submission;
|
||||
}
|
||||
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because " + user.getIdentity() + " is not the user who submitted the request");
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because " + user.getIdentity() + " is not the user who submitted the request.");
|
||||
}
|
||||
|
||||
public Lineage computeLineage(final String flowFileUUID, final NiFiUser user) throws IOException {
|
||||
|
@ -520,14 +520,14 @@ public class VolatileProvenanceRepository implements ProvenanceRepository {
|
|||
}
|
||||
|
||||
if (user == null) {
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because no user id was provided");
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Lineage Submission because no user id was provided in the lineage request.");
|
||||
}
|
||||
|
||||
if (userId == null || userId.equals(user.getIdentity())) {
|
||||
return submission;
|
||||
}
|
||||
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Query Submission because " + user.getIdentity() + " is not the user who submitted the request");
|
||||
throw new AccessDeniedException("Cannot retrieve Provenance Lineage Submission because " + user.getIdentity() + " is not the user who submitted the request.");
|
||||
}
|
||||
|
||||
public Lineage expandSpawnEventParents(String identifier) throws IOException {
|
||||
|
|
|
@ -179,13 +179,13 @@ public class RangerNiFiAuthorizer implements Authorizer {
|
|||
final boolean doesPolicyExist = nifiPlugin.doesPolicyExist(request.getResource().getIdentifier());
|
||||
|
||||
if (doesPolicyExist) {
|
||||
// a policy does exist for the resource so we were really denied access here
|
||||
final String reason = result == null ? null : result.getReason();
|
||||
if (reason == null) {
|
||||
return AuthorizationResult.denied();
|
||||
} else {
|
||||
return AuthorizationResult.denied(result.getReason());
|
||||
if (reason != null) {
|
||||
logger.debug(String.format("Unable to authorize %s due to %s", identity, reason));
|
||||
}
|
||||
|
||||
// a policy does exist for the resource so we were really denied access here
|
||||
return AuthorizationResult.denied(request.getExplanationSupplier().get());
|
||||
} else {
|
||||
// a policy doesn't exist so return resource not found so NiFi can work back up the resource hierarchy
|
||||
return AuthorizationResult.resourceNotFound();
|
||||
|
|
|
@ -467,6 +467,11 @@ public class TestRangerNiFiAuthorizer {
|
|||
public String getName() {
|
||||
return "/system";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return "system";
|
||||
}
|
||||
})
|
||||
.action(RequestAction.WRITE)
|
||||
.identity("admin")
|
||||
|
@ -526,6 +531,11 @@ public class TestRangerNiFiAuthorizer {
|
|||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSafeDescription() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue