Repository: nifi Updated Branches: refs/heads/master d838f6129 -> feaa4c9db
NIFI-2757: Site-to-Site with DN mapping Added DN identity mapping pattern support to Site-to-Site client authorization. This closes #1010. Signed-off-by: Bryan Bende <bbe...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/feaa4c9d Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/feaa4c9d Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/feaa4c9d Branch: refs/heads/master Commit: feaa4c9db82f6d29777d82df45beb43879be87cf Parents: d838f61 Author: Koji Kawamura <ijokaruma...@apache.org> Authored: Tue Sep 13 13:24:59 2016 +0900 Committer: Bryan Bende <bbe...@apache.org> Committed: Mon Sep 19 12:56:54 2016 -0400 ---------------------------------------------------------------------- .../apache/nifi/controller/FlowController.java | 4 +- .../nifi/remote/StandardRootGroupPort.java | 15 ++- .../nifi/remote/TestStandardRootGroupPort.java | 100 +++++++++++++++++++ 3 files changed, 115 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi/blob/feaa4c9d/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java index b1577b7..b42f3ae 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java @@ -1166,7 +1166,7 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R name = requireNonNull(name).intern(); verifyPortIdDoesNotExist(id); return new StandardRootGroupPort(id, name, null, TransferDirection.RECEIVE, ConnectableType.INPUT_PORT, - authorizer, getBulletinRepository(), processScheduler, Boolean.TRUE.equals(isSiteToSiteSecure)); + authorizer, getBulletinRepository(), processScheduler, Boolean.TRUE.equals(isSiteToSiteSecure), nifiProperties); } /** @@ -1186,7 +1186,7 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R name = requireNonNull(name).intern(); verifyPortIdDoesNotExist(id); return new StandardRootGroupPort(id, name, null, TransferDirection.SEND, ConnectableType.OUTPUT_PORT, - authorizer, getBulletinRepository(), processScheduler, Boolean.TRUE.equals(isSiteToSiteSecure)); + authorizer, getBulletinRepository(), processScheduler, Boolean.TRUE.equals(isSiteToSiteSecure), nifiProperties); } /** http://git-wip-us.apache.org/repos/asf/nifi/blob/feaa4c9d/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 a496652..4c78dd5 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 @@ -24,6 +24,8 @@ 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.authorization.util.IdentityMapping; +import org.apache.nifi.authorization.util.IdentityMappingUtil; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.controller.AbstractPort; @@ -48,6 +50,7 @@ import org.apache.nifi.reporting.BulletinRepository; import org.apache.nifi.reporting.ComponentType; import org.apache.nifi.reporting.Severity; import org.apache.nifi.scheduling.SchedulingStrategy; +import org.apache.nifi.util.NiFiProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,6 +60,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -79,6 +83,8 @@ public class StandardRootGroupPort extends AbstractPort implements RootGroupPort private final ProcessScheduler processScheduler; private final boolean secure; private final Authorizer authorizer; + private final NiFiProperties nifiProperties; + private final List<IdentityMapping> identityMappings; @SuppressWarnings("unused") private final BulletinRepository bulletinRepository; @@ -94,13 +100,16 @@ public class StandardRootGroupPort extends AbstractPort implements RootGroupPort public StandardRootGroupPort(final String id, final String name, final ProcessGroup processGroup, final TransferDirection direction, final ConnectableType type, final Authorizer authorizer, - final BulletinRepository bulletinRepository, final ProcessScheduler scheduler, final boolean secure) { + final BulletinRepository bulletinRepository, final ProcessScheduler scheduler, final boolean secure, + final NiFiProperties nifiProperties) { super(id, name, processGroup, type, scheduler); this.processScheduler = scheduler; setScheduldingPeriod(MINIMUM_SCHEDULING_NANOS + " nanos"); this.authorizer = authorizer; this.secure = secure; + this.nifiProperties = nifiProperties; + this.identityMappings = IdentityMappingUtil.getIdentityMappings(nifiProperties); this.bulletinRepository = bulletinRepository; this.scheduler = scheduler; setYieldPeriod("100 millis"); @@ -357,7 +366,9 @@ public class StandardRootGroupPort extends AbstractPort implements RootGroupPort return new StandardPortAuthorizationResult(false, "User DN is not known"); } - return checkUserAuthorization(new StandardNiFiUser(dn)); + final String identity = IdentityMappingUtil.mapIdentity(dn, identityMappings); + + return checkUserAuthorization(new StandardNiFiUser(identity)); } @Override http://git-wip-us.apache.org/repos/asf/nifi/blob/feaa4c9d/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/java/org/apache/nifi/remote/TestStandardRootGroupPort.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/java/org/apache/nifi/remote/TestStandardRootGroupPort.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/java/org/apache/nifi/remote/TestStandardRootGroupPort.java new file mode 100644 index 0000000..affa9d9 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/java/org/apache/nifi/remote/TestStandardRootGroupPort.java @@ -0,0 +1,100 @@ +/* + * 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.remote; + +import org.apache.nifi.authorization.AuthorizationRequest; +import org.apache.nifi.authorization.AuthorizationResult; +import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.connectable.ConnectableType; +import org.apache.nifi.controller.ProcessScheduler; +import org.apache.nifi.groups.ProcessGroup; +import org.apache.nifi.reporting.BulletinRepository; +import org.apache.nifi.util.NiFiProperties; +import org.junit.Assert; +import org.junit.Test; + +import java.util.LinkedHashSet; +import java.util.Set; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +public class TestStandardRootGroupPort { + + private RootGroupPort createRootGroupPort(NiFiProperties nifiProperties) { + final BulletinRepository bulletinRepository = mock(BulletinRepository.class); + final ProcessScheduler processScheduler = null; + + final Authorizer authorizer = mock(Authorizer.class); + doAnswer(invocation -> { + final AuthorizationRequest request = invocation.getArgumentAt(0, AuthorizationRequest.class); + if ("no...@nifi.test".equals(request.getIdentity())) { + return AuthorizationResult.approved(); + } + return AuthorizationResult.denied(); + }).when(authorizer).authorize(any(AuthorizationRequest.class)); + + final ProcessGroup processGroup = mock(ProcessGroup.class); + doReturn("process-group-id").when(processGroup).getIdentifier(); + + return new StandardRootGroupPort("id", "name", processGroup, + TransferDirection.SEND, ConnectableType.INPUT_PORT, authorizer, bulletinRepository, + processScheduler, true, nifiProperties); + } + + @Test + public void testCheckUserAuthorizationByDn() { + + final NiFiProperties nifiProperties = mock(NiFiProperties.class); + + final RootGroupPort port = createRootGroupPort(nifiProperties); + + PortAuthorizationResult authResult = port.checkUserAuthorization("CN=node1, OU=nifi.test"); + Assert.assertFalse(authResult.isAuthorized()); + + authResult = port.checkUserAuthorization("no...@nifi.test"); + Assert.assertTrue(authResult.isAuthorized()); + } + + @Test + public void testCheckUserAuthorizationByMappedDn() { + + final NiFiProperties nifiProperties = mock(NiFiProperties.class); + final String mapKey = ".dn"; + Set<String> propertyKeys = new LinkedHashSet<>(); + propertyKeys.add(NiFiProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX + mapKey); + propertyKeys.add(NiFiProperties.SECURITY_IDENTITY_MAPPING_VALUE_PREFIX + mapKey); + doReturn(propertyKeys).when(nifiProperties).getPropertyKeys(); + + final String mapPattern = "^CN=(.*?), OU=(.*?)$"; + final String mapValue = "$1@$2"; + doReturn(mapPattern).when(nifiProperties).getProperty(eq(NiFiProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX + mapKey)); + doReturn(mapValue).when(nifiProperties).getProperty(eq(NiFiProperties.SECURITY_IDENTITY_MAPPING_VALUE_PREFIX + mapKey)); + + final RootGroupPort port = createRootGroupPort(nifiProperties); + + PortAuthorizationResult authResult = port.checkUserAuthorization("CN=node2, OU=nifi.test"); + Assert.assertFalse(authResult.isAuthorized()); + + authResult = port.checkUserAuthorization("CN=node1, OU=nifi.test"); + Assert.assertTrue(authResult.isAuthorized()); + } + +}