Repository: nifi Updated Branches: refs/heads/master bc7c42efa -> ae251c1a6
NIFI-2718: Show HTTP S2S Auth error on bulletin This commit fixes following two issues, that happens when a Root Group Port policy for S2S data transfer is removed at a remote NiFi, after a client NiFi has connected to that port: 1. At client side, Remote Process Group should show that authorization is failing on its bulletin, but the Exception is caught and ignored. Nothing is shown on the UI with HTTP transport protocol. RAW S2S shows error on RPG bulletin. This commit fixes HTTP S2S to behave the same. 2. At server side, corresponding input-port or output-port should show that it is accessed by an unauthorized client on its bulletin, but it's not shown with HTTP transport protocol. RAW S2S shows warning messages for this. This commit fixes HTTP S2S to behave the same. In order to fix the 2nd issue above, request authorization at DataTransferResource is changed from using DataTransferAuthorizable directly, to call RootGroupPort.checkUserAuthorization(). Because the blettin is tied to the Port instance and it's difficult to produce blettin message from this resource. Since RootGroupPort.checkUserAuthorization uses DataTransferAuthorizable inside, the check logic stays the same as before. Adding a RootGroupPortAuthorizable to provide access to necessary components for performing the authorization. This closes #996 Project: http://git-wip-us.apache.org/repos/asf/nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/ae251c1a Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/ae251c1a Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/ae251c1a Branch: refs/heads/master Commit: ae251c1a6f0550c02deee3b42ba64aadc934483e Parents: bc7c42e Author: Koji Kawamura <[email protected]> Authored: Thu Sep 8 14:37:30 2016 +0900 Committer: Matt Gilman <[email protected]> Committed: Thu Sep 8 13:43:38 2016 -0400 ---------------------------------------------------------------------- .../nifi/remote/client/http/HttpClient.java | 7 ++- .../remote/util/SiteToSiteRestApiClient.java | 11 +++- .../nifi/remote/client/http/TestHttpClient.java | 56 ++++++++++++++---- .../org/apache/nifi/remote/RootGroupPort.java | 14 +++++ .../nifi/remote/StandardRootGroupPort.java | 23 ++++++-- .../nifi/authorization/AuthorizableLookup.java | 16 ++++++ .../RootGroupPortAuthorizable.java | 40 +++++++++++++ .../StandardAuthorizableLookup.java | 60 ++++++++++++++++++++ .../nifi/web/api/DataTransferResource.java | 23 ++++---- .../src/main/resources/nifi-web-api-context.xml | 1 - 10 files changed, 217 insertions(+), 34 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/http/HttpClient.java ---------------------------------------------------------------------- diff --git a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/http/HttpClient.java b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/http/HttpClient.java index 75bd3a6..9e66b72 100644 --- a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/http/HttpClient.java +++ b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/http/HttpClient.java @@ -166,10 +166,13 @@ public class HttpClient extends AbstractSiteToSiteClient implements PeerStatusPr commSession.setUserDn(apiClient.getTrustedPeerDn()); } catch (final Exception e) { apiClient.close(); - logger.debug("Penalizing a peer due to {}", e.getMessage()); + logger.warn("Penalizing a peer {} due to {}", peer, e.toString()); peerSelector.penalize(peer, penaltyMillis); - if (e instanceof UnknownPortException || e instanceof PortNotRunningException) { + // Following exceptions will be thrown even if we tried other peers, so throw it. + if (e instanceof UnknownPortException + || e instanceof PortNotRunningException + || e instanceof HandshakeException) { throw e; } http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/util/SiteToSiteRestApiClient.java ---------------------------------------------------------------------- diff --git a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/util/SiteToSiteRestApiClient.java b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/util/SiteToSiteRestApiClient.java index c7249b1..9bc8792 100644 --- a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/util/SiteToSiteRestApiClient.java +++ b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/util/SiteToSiteRestApiClient.java @@ -59,6 +59,7 @@ import org.apache.nifi.events.EventReporter; import org.apache.nifi.remote.Peer; import org.apache.nifi.remote.TransferDirection; import org.apache.nifi.remote.client.http.TransportProtocolVersionNegotiator; +import org.apache.nifi.remote.exception.HandshakeException; import org.apache.nifi.remote.exception.PortNotRunningException; import org.apache.nifi.remote.exception.ProtocolException; import org.apache.nifi.remote.exception.UnknownPortException; @@ -137,6 +138,7 @@ public class SiteToSiteRestApiClient implements Closeable { private static final int RESPONSE_CODE_CREATED = 201; private static final int RESPONSE_CODE_ACCEPTED = 202; private static final int RESPONSE_CODE_BAD_REQUEST = 400; + private static final int RESPONSE_CODE_FORBIDDEN = 403; private static final int RESPONSE_CODE_NOT_FOUND = 404; private static final Logger logger = LoggerFactory.getLogger(SiteToSiteRestApiClient.class); @@ -500,7 +502,7 @@ public class SiteToSiteRestApiClient implements Closeable { @Override public void failed(Exception ex) { - final String msg = String.format("Failed to create transactino for %s", post.getURI()); + final String msg = String.format("Failed to create transaction for %s", post.getURI()); logger.error(msg, ex); eventReporter.reportEvent(Severity.WARNING, EVENT_CATEGORY, msg); } @@ -953,7 +955,12 @@ public class SiteToSiteRestApiClient implements Closeable { case PORT_NOT_IN_VALID_STATE: return new PortNotRunningException(errEntity.getMessage()); default: - return new IOException("Unexpected response code: " + responseCode + " errCode:" + errCode + " errMessage:" + errEntity.getMessage()); + switch (responseCode) { + case RESPONSE_CODE_FORBIDDEN : + return new HandshakeException(errEntity.getMessage()); + default: + return new IOException("Unexpected response code: " + responseCode + " errCode:" + errCode + " errMessage:" + errEntity.getMessage()); + } } } http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/http/TestHttpClient.java ---------------------------------------------------------------------- diff --git a/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/http/TestHttpClient.java b/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/http/TestHttpClient.java index 1dcca2c..67b676e 100644 --- a/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/http/TestHttpClient.java +++ b/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/http/TestHttpClient.java @@ -23,6 +23,7 @@ import org.apache.nifi.remote.TransferDirection; import org.apache.nifi.remote.client.KeystoreType; import org.apache.nifi.remote.client.SiteToSiteClient; import org.apache.nifi.remote.codec.StandardFlowFileCodec; +import org.apache.nifi.remote.exception.HandshakeException; import org.apache.nifi.remote.io.CompressionInputStream; import org.apache.nifi.remote.io.CompressionOutputStream; import org.apache.nifi.remote.protocol.DataPacket; @@ -182,6 +183,18 @@ public class TestHttpClient { } + public static class PortTransactionsAccessDeniedServlet extends HttpServlet { + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + respondWithText(resp, "Unable to perform the desired action" + + " due to insufficient permissions. Contact the system administrator.", 403); + + } + + } + public static class InputPortTransactionServlet extends HttpServlet { @Override @@ -432,6 +445,7 @@ public class TestHttpClient { servletHandler.addServletWithMapping(SiteInfoServlet.class, "/site-to-site"); servletHandler.addServletWithMapping(PeersServlet.class, "/site-to-site/peers"); + servletHandler.addServletWithMapping(PortTransactionsAccessDeniedServlet.class, "/data-transfer/input-ports/input-access-denied-id/transactions"); servletHandler.addServletWithMapping(PortTransactionsServlet.class, "/data-transfer/input-ports/input-running-id/transactions"); servletHandler.addServletWithMapping(InputPortTransactionServlet.class, "/data-transfer/input-ports/input-running-id/transactions/transaction-id"); servletHandler.addServletWithMapping(FlowFilesServlet.class, "/data-transfer/input-ports/input-running-id/transactions/transaction-id/flow-files"); @@ -569,54 +583,55 @@ public class TestHttpClient { inputPorts = new HashSet<>(); final PortDTO runningInputPort = new PortDTO(); - runningInputPort.setId("running-input-port"); - inputPorts.add(runningInputPort); runningInputPort.setName("input-running"); runningInputPort.setId("input-running-id"); runningInputPort.setType("INPUT_PORT"); runningInputPort.setState(ScheduledState.RUNNING.name()); + inputPorts.add(runningInputPort); final PortDTO timeoutInputPort = new PortDTO(); - timeoutInputPort.setId("timeout-input-port"); - inputPorts.add(timeoutInputPort); timeoutInputPort.setName("input-timeout"); timeoutInputPort.setId("input-timeout-id"); timeoutInputPort.setType("INPUT_PORT"); timeoutInputPort.setState(ScheduledState.RUNNING.name()); + inputPorts.add(timeoutInputPort); final PortDTO timeoutDataExInputPort = new PortDTO(); - timeoutDataExInputPort.setId("timeout-dataex-input-port"); - inputPorts.add(timeoutDataExInputPort); timeoutDataExInputPort.setName("input-timeout-data-ex"); timeoutDataExInputPort.setId("input-timeout-data-ex-id"); timeoutDataExInputPort.setType("INPUT_PORT"); timeoutDataExInputPort.setState(ScheduledState.RUNNING.name()); + inputPorts.add(timeoutDataExInputPort); + + final PortDTO accessDeniedInputPort = new PortDTO(); + accessDeniedInputPort.setName("input-access-denied"); + accessDeniedInputPort.setId("input-access-denied-id"); + accessDeniedInputPort.setType("INPUT_PORT"); + accessDeniedInputPort.setState(ScheduledState.RUNNING.name()); + inputPorts.add(accessDeniedInputPort); outputPorts = new HashSet<>(); final PortDTO runningOutputPort = new PortDTO(); - runningOutputPort.setId("running-output-port"); - outputPorts.add(runningOutputPort); runningOutputPort.setName("output-running"); runningOutputPort.setId("output-running-id"); runningOutputPort.setType("OUTPUT_PORT"); runningOutputPort.setState(ScheduledState.RUNNING.name()); + outputPorts.add(runningOutputPort); final PortDTO timeoutOutputPort = new PortDTO(); - timeoutOutputPort.setId("timeout-output-port"); - outputPorts.add(timeoutOutputPort); timeoutOutputPort.setName("output-timeout"); timeoutOutputPort.setId("output-timeout-id"); timeoutOutputPort.setType("OUTPUT_PORT"); timeoutOutputPort.setState(ScheduledState.RUNNING.name()); + outputPorts.add(timeoutOutputPort); final PortDTO timeoutDataExOutputPort = new PortDTO(); - timeoutDataExOutputPort.setId("timeout-dataex-output-port"); - outputPorts.add(timeoutDataExOutputPort); timeoutDataExOutputPort.setName("output-timeout-data-ex"); timeoutDataExOutputPort.setId("output-timeout-data-ex-id"); timeoutDataExOutputPort.setType("OUTPUT_PORT"); timeoutDataExOutputPort.setState(ScheduledState.RUNNING.name()); + outputPorts.add(timeoutDataExOutputPort); } @@ -788,6 +803,23 @@ public class TestHttpClient { } @Test + public void testSendAccessDeniedHTTPS() throws Exception { + + try ( + final SiteToSiteClient client = getDefaultBuilderHTTPS() + .portName("input-access-denied") + .build() + ) { + try { + client.createTransaction(TransferDirection.SEND); + fail("Handshake exception should be thrown."); + } catch (HandshakeException e) { + } + } + + } + + @Test public void testSendSuccessHTTPS() throws Exception { try ( http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/remote/RootGroupPort.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/remote/RootGroupPort.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/remote/RootGroupPort.java index 43363c0..a1e1320 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/remote/RootGroupPort.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/remote/RootGroupPort.java @@ -16,6 +16,7 @@ */ package org.apache.nifi.remote; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.connectable.Port; import org.apache.nifi.remote.exception.BadRequestException; import org.apache.nifi.remote.exception.NotAuthorizedException; @@ -41,12 +42,25 @@ public interface RootGroupPort extends Port { * and returns a {@link PortAuthorizationResult} indicating why the user is * unauthorized if this assumption fails * + * {@link #checkUserAuthorization(NiFiUser)} should be used if applicable + * because NiFiUser has additional context such as chained user. + * * @param dn dn of user * @return result */ PortAuthorizationResult checkUserAuthorization(String dn); /** + * Verifies that the specified user is authorized to interact with this port + * and returns a {@link PortAuthorizationResult} indicating why the user is + * unauthorized if this assumption fails + * + * @param user to authorize + * @return result + */ + PortAuthorizationResult checkUserAuthorization(NiFiUser user); + + /** * Receives data from the given stream * * @param peer peer http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRootGroupPort.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRootGroupPort.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRootGroupPort.java index 64c4b7f..a8bf127 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRootGroupPort.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRootGroupPort.java @@ -22,6 +22,7 @@ import org.apache.nifi.authorization.Authorizer; import org.apache.nifi.authorization.RequestAction; import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.authorization.resource.DataTransferAuthorizable; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.authorization.user.StandardNiFiUser; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.connectable.ConnectableType; @@ -345,23 +346,35 @@ public class StandardRootGroupPort extends AbstractPort implements RootGroupPort @Override public PortAuthorizationResult checkUserAuthorization(final String dn) { + if (dn == null) { + final String message = String.format("%s authorization failed for user %s because the DN is unknown", this, dn); + logger.warn(message); + eventReporter.reportEvent(Severity.WARNING, CATEGORY, message); + return new StandardPortAuthorizationResult(false, "User DN is not known"); + } + + return checkUserAuthorization(new StandardNiFiUser(dn)); + } + + @Override + public PortAuthorizationResult checkUserAuthorization(NiFiUser user) { if (!secure) { return new StandardPortAuthorizationResult(true, "Site-to-Site is not Secure"); } - if (dn == null) { - final String message = String.format("%s authorization failed for user %s because the DN is unknown", this, dn); + if (user == null) { + final String message = String.format("%s authorization failed because the user is unknown", this, user); logger.warn(message); eventReporter.reportEvent(Severity.WARNING, CATEGORY, message); - return new StandardPortAuthorizationResult(false, "User DN is not known"); + return new StandardPortAuthorizationResult(false, "User is not known"); } // perform the authorization final Authorizable dataTransferAuthorizable = new DataTransferAuthorizable(this); - final AuthorizationResult result = dataTransferAuthorizable.checkAuthorization(authorizer, RequestAction.WRITE, new StandardNiFiUser(dn)); + final AuthorizationResult result = dataTransferAuthorizable.checkAuthorization(authorizer, RequestAction.WRITE, user); if (!Result.Approved.equals(result.getResult())) { - final String message = String.format("%s authorization failed for user %s because %s", this, dn, result.getExplanation()); + final String message = String.format("%s authorization failed for user %s because %s", this, user.getIdentity(), result.getExplanation()); logger.warn(message); eventReporter.reportEvent(Severity.WARNING, CATEGORY, message); return new StandardPortAuthorizationResult(false, message); http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java index 0cd0548..b3ef20c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java @@ -61,6 +61,22 @@ public interface AuthorizableLookup { Authorizable getCounters(); /** + * Get the authorizable RootGroup InputPort. + * + * @param id input port id + * @return authorizable + */ + RootGroupPortAuthorizable getRootGroupInputPort(String id); + + /** + * Get the authorizable RootGroup OutputPort. + * + * @param id output port id + * @return authorizable + */ + RootGroupPortAuthorizable getRootGroupOutputPort(String id); + + /** * Get the authorizable InputPort. * * @param id input port id http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/RootGroupPortAuthorizable.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/RootGroupPortAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/RootGroupPortAuthorizable.java new file mode 100644 index 0000000..ec29c6a --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/RootGroupPortAuthorizable.java @@ -0,0 +1,40 @@ +/* + * 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; + +import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.user.NiFiUser; + +/** + * Authorizable for a RootGroupPort. + */ +public interface RootGroupPortAuthorizable { + /** + * Returns the authorizable for this RootGroupPort. Non null + * + * @return authorizable + */ + Authorizable getAuthorizable(); + + /** + * Checks the authorization for the specified user. + * + * @param user user + * @return authorization result + */ + AuthorizationResult checkAuthorization(NiFiUser user); +} http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java index 5880808..84bf7b3 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java @@ -24,9 +24,11 @@ import org.apache.nifi.authorization.resource.DataTransferAuthorizable; import org.apache.nifi.authorization.resource.ResourceFactory; import org.apache.nifi.authorization.resource.ResourceType; import org.apache.nifi.authorization.resource.TenantAuthorizable; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.connectable.Connectable; import org.apache.nifi.connectable.Connection; +import org.apache.nifi.connectable.Port; import org.apache.nifi.controller.ConfiguredComponent; import org.apache.nifi.controller.ProcessorNode; import org.apache.nifi.controller.ReportingTaskNode; @@ -35,6 +37,8 @@ import org.apache.nifi.controller.service.ControllerServiceNode; import org.apache.nifi.controller.service.ControllerServiceReference; import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.RemoteProcessGroup; +import org.apache.nifi.remote.PortAuthorizationResult; +import org.apache.nifi.remote.RootGroupPort; import org.apache.nifi.web.ResourceNotFoundException; import org.apache.nifi.web.controller.ControllerFacade; import org.apache.nifi.web.dao.AccessPolicyDAO; @@ -164,6 +168,62 @@ class StandardAuthorizableLookup implements AuthorizableLookup { } @Override + public RootGroupPortAuthorizable getRootGroupInputPort(String id) { + final Port inputPort = inputPortDAO.getPort(id); + + if (!(inputPort instanceof RootGroupPort)) { + throw new IllegalArgumentException(String.format("The specified id '%s' does not represent an input port in the root group.", id)); + } + + final DataTransferAuthorizable baseAuthorizable = new DataTransferAuthorizable(inputPort); + return new RootGroupPortAuthorizable() { + @Override + public Authorizable getAuthorizable() { + return baseAuthorizable; + } + + @Override + public AuthorizationResult checkAuthorization(NiFiUser user) { + // perform the authorization of the user by using the underlying component, ensures consistent authorization with raw s2s + final PortAuthorizationResult authorizationResult = ((RootGroupPort) inputPort).checkUserAuthorization(user); + if (authorizationResult.isAuthorized()) { + return AuthorizationResult.approved(); + } else { + return AuthorizationResult.denied(authorizationResult.getExplanation()); + } + } + }; + } + + @Override + public RootGroupPortAuthorizable getRootGroupOutputPort(String id) { + final Port outputPort = outputPortDAO.getPort(id); + + if (!(outputPort instanceof RootGroupPort)) { + throw new IllegalArgumentException(String.format("The specified id '%s' does not represent an output port in the root group.", id)); + } + + final DataTransferAuthorizable baseAuthorizable = new DataTransferAuthorizable(outputPort); + return new RootGroupPortAuthorizable() { + @Override + public Authorizable getAuthorizable() { + return baseAuthorizable; + } + + @Override + public AuthorizationResult checkAuthorization(NiFiUser user) { + // perform the authorization of the user by using the underlying component, ensures consistent authorization with raw s2s + final PortAuthorizationResult authorizationResult = ((RootGroupPort) outputPort).checkUserAuthorization(user); + if (authorizationResult.isAuthorized()) { + return AuthorizationResult.approved(); + } else { + return AuthorizationResult.denied(authorizationResult.getExplanation()); + } + } + }; + } + + @Override public Authorizable getInputPort(final String id) { return inputPortDAO.getPort(id); } http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/DataTransferResource.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/DataTransferResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/DataTransferResource.java index f859b8e..831b2f5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/DataTransferResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/DataTransferResource.java @@ -23,10 +23,11 @@ import com.wordnik.swagger.annotations.ApiResponse; import com.wordnik.swagger.annotations.ApiResponses; import com.wordnik.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authorization.AccessDeniedException; import org.apache.nifi.authorization.AuthorizableLookup; -import org.apache.nifi.authorization.Authorizer; -import org.apache.nifi.authorization.RequestAction; -import org.apache.nifi.authorization.resource.DataTransferAuthorizable; +import org.apache.nifi.authorization.AuthorizationResult; +import org.apache.nifi.authorization.AuthorizationResult.Result; +import org.apache.nifi.authorization.RootGroupPortAuthorizable; import org.apache.nifi.authorization.resource.ResourceType; import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.authorization.user.NiFiUserUtils; @@ -107,7 +108,6 @@ public class DataTransferResource extends ApplicationResource { private static final String PORT_TYPE_INPUT = "input-ports"; private static final String PORT_TYPE_OUTPUT = "output-ports"; - private Authorizer authorizer; private NiFiServiceFacade serviceFacade; private final ResponseCreator responseCreator = new ResponseCreator(); private final VersionNegotiator transportProtocolVersionNegotiator = new TransportProtocolVersionNegotiator(1); @@ -133,15 +133,18 @@ public class DataTransferResource extends ApplicationResource { } // get the authorizable - final DataTransferAuthorizable authorizable; + final RootGroupPortAuthorizable authorizable; if (ResourceType.InputPort.equals(resourceType)) { - authorizable = new DataTransferAuthorizable(lookup.getInputPort(identifier)); + authorizable = lookup.getRootGroupInputPort(identifier); } else { - authorizable = new DataTransferAuthorizable(lookup.getOutputPort(identifier)); + authorizable = lookup.getRootGroupOutputPort(identifier); } // perform the authorization - authorizable.authorize(authorizer, RequestAction.WRITE, user); + final AuthorizationResult authorizationResult = authorizable.checkAuthorization(user); + if (!Result.Approved.equals(authorizationResult.getResult())) { + throw new AccessDeniedException(authorizationResult.getExplanation()); + } } @POST @@ -831,10 +834,6 @@ public class DataTransferResource extends ApplicationResource { // setters - public void setAuthorizer(Authorizer authorizer) { - this.authorizer = authorizer; - } - public void setServiceFacade(NiFiServiceFacade serviceFacade) { this.serviceFacade = serviceFacade; } http://git-wip-us.apache.org/repos/asf/nifi/blob/ae251c1a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml index 316dce5..7cfe448 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml @@ -231,7 +231,6 @@ <property name="properties" ref="nifiProperties"/> <property name="clusterCoordinator" ref="clusterCoordinator"/> <property name="requestReplicator" ref="requestReplicator" /> - <property name="authorizer" ref="authorizer"/> <property name="serviceFacade" ref="serviceFacade"/> <property name="flowController" ref="flowController" /> </bean>
