Repository: knox Updated Branches: refs/heads/master 19166412f -> 79493c2d8
KNOX-1522 - Add HA support for HadoopAuthProvider Signed-off-by: Kevin Risden <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/79493c2d Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/79493c2d Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/79493c2d Branch: refs/heads/master Commit: 79493c2d8219c48c7a64c032d0b3e246a08f4426 Parents: 1916641 Author: Kevin Risden <[email protected]> Authored: Thu Oct 11 10:29:20 2018 -0400 Committer: Kevin Risden <[email protected]> Committed: Thu Oct 11 14:53:28 2018 -0400 ---------------------------------------------------------------------- gateway-provider-security-hadoopauth/pom.xml | 16 +++ .../gateway/hadoopauth/HadoopAuthMessages.java | 7 + .../deploy/HadoopAuthDeploymentContributor.java | 54 ++++++-- .../HadoopAuthDeploymentContributorTest.java | 138 +++++++++++++++++++ 4 files changed, 205 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/79493c2d/gateway-provider-security-hadoopauth/pom.xml ---------------------------------------------------------------------- diff --git a/gateway-provider-security-hadoopauth/pom.xml b/gateway-provider-security-hadoopauth/pom.xml index 4a997f2..3353b68 100755 --- a/gateway-provider-security-hadoopauth/pom.xml +++ b/gateway-provider-security-hadoopauth/pom.xml @@ -53,6 +53,11 @@ </dependency> <dependency> + <groupId>org.jboss.shrinkwrap</groupId> + <artifactId>shrinkwrap-api</artifactId> + </dependency> + + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> @@ -64,9 +69,20 @@ </dependency> <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-core</artifactId> + <scope>test</scope> + </dependency> + + <dependency> <groupId>org.apache.knox</groupId> <artifactId>gateway-test-utils</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>${gateway-group}</groupId> + <artifactId>gateway-server</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> http://git-wip-us.apache.org/repos/asf/knox/blob/79493c2d/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/HadoopAuthMessages.java ---------------------------------------------------------------------- diff --git a/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/HadoopAuthMessages.java b/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/HadoopAuthMessages.java index 2a92d36..859e901 100755 --- a/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/HadoopAuthMessages.java +++ b/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/HadoopAuthMessages.java @@ -20,11 +20,18 @@ package org.apache.knox.gateway.hadoopauth; import org.apache.knox.gateway.i18n.messages.Message; import org.apache.knox.gateway.i18n.messages.MessageLevel; import org.apache.knox.gateway.i18n.messages.Messages; +import org.apache.knox.gateway.i18n.messages.StackTrace; @Messages(logger="org.apache.knox.gateway.provider.global.hadoopauth") public interface HadoopAuthMessages { @Message( level = MessageLevel.DEBUG, text = "Hadoop Authentication Asserted Principal: {0}" ) void hadoopAuthAssertedPrincipal(String name); + + @Message( level = MessageLevel.ERROR, text = "Alias service exception: {0}" ) + void aliasServiceException(@StackTrace( level = MessageLevel.DEBUG ) Exception e); + + @Message( level = MessageLevel.ERROR, text = "Unable to get password for {0}: {1}" ) + void unableToGetPassword(String name, @StackTrace( level = MessageLevel.DEBUG ) Exception e); } http://git-wip-us.apache.org/repos/asf/knox/blob/79493c2d/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/deploy/HadoopAuthDeploymentContributor.java ---------------------------------------------------------------------- diff --git a/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/deploy/HadoopAuthDeploymentContributor.java b/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/deploy/HadoopAuthDeploymentContributor.java index 92c2bb6..4cc4925 100755 --- a/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/deploy/HadoopAuthDeploymentContributor.java +++ b/gateway-provider-security-hadoopauth/src/main/java/org/apache/knox/gateway/hadoopauth/deploy/HadoopAuthDeploymentContributor.java @@ -21,6 +21,12 @@ import org.apache.knox.gateway.deploy.DeploymentContext; import org.apache.knox.gateway.deploy.ProviderDeploymentContributorBase; import org.apache.knox.gateway.descriptor.FilterParamDescriptor; import org.apache.knox.gateway.descriptor.ResourceDescriptor; +import org.apache.knox.gateway.hadoopauth.HadoopAuthMessages; +import org.apache.knox.gateway.hadoopauth.filter.HadoopAuthFilter; +import org.apache.knox.gateway.hadoopauth.filter.HadoopAuthPostFilter; +import org.apache.knox.gateway.i18n.messages.MessagesFactory; +import org.apache.knox.gateway.services.security.AliasService; +import org.apache.knox.gateway.services.security.AliasServiceException; import org.apache.knox.gateway.topology.Provider; import org.apache.knox.gateway.topology.Service; @@ -30,14 +36,16 @@ import java.util.Locale; import java.util.Map; import java.util.Map.Entry; -public class HadoopAuthDeploymentContributor extends - ProviderDeploymentContributorBase { +public class HadoopAuthDeploymentContributor extends ProviderDeploymentContributorBase { - private static final String ROLE = "authentication"; - private static final String NAME = "HadoopAuth"; + private static HadoopAuthMessages log = MessagesFactory.get( HadoopAuthMessages.class ); - private static final String HADOOPAUTH_FILTER_CLASSNAME = "org.apache.knox.gateway.hadoopauth.filter.HadoopAuthFilter"; - private static final String HADOOPAUTH_POSTFILTER_CLASSNAME = "org.apache.knox.gateway.hadoopauth.filter.HadoopAuthPostFilter"; + private static final String HADOOPAUTH_FILTER_CLASSNAME = HadoopAuthFilter.class.getCanonicalName(); + private static final String HADOOPAUTH_POSTFILTER_CLASSNAME = HadoopAuthPostFilter.class.getCanonicalName(); + + public static final String ROLE = "authentication"; + public static final String NAME = "HadoopAuth"; + private AliasService as; @Override public String getRole() { @@ -49,6 +57,10 @@ public class HadoopAuthDeploymentContributor extends return NAME; } + public void setAliasService(AliasService as) { + this.as = as; + } + @Override public void initializeContribution(DeploymentContext context) { super.initializeContribution(context); @@ -57,15 +69,37 @@ public class HadoopAuthDeploymentContributor extends @Override public void contributeFilter(DeploymentContext context, Provider provider, Service service, ResourceDescriptor resource, List<FilterParamDescriptor> params) { + String clusterName = context.getTopology().getName(); + + List<String> aliases = new ArrayList<>(); + try { + aliases = this.as.getAliasesForCluster(clusterName); + } catch (AliasServiceException e) { + log.aliasServiceException(e); + } + // blindly add all the provider params as filter init params if (params == null) { - params = new ArrayList<FilterParamDescriptor>(); + params = new ArrayList<>(); } Map<String, String> providerParams = provider.getParams(); for(Entry<String, String> entry : providerParams.entrySet()) { - params.add( resource.createFilterParam().name( entry.getKey().toLowerCase(Locale.ROOT) ).value( entry.getValue() ) ); + String key = entry.getKey().toLowerCase(Locale.ROOT); + String value = null; + if(aliases.contains(key)) { + try { + value = String.valueOf(this.as.getPasswordFromAliasForCluster(clusterName, key)); + } catch (AliasServiceException e) { + log.unableToGetPassword(key, e); + } + } else { + value = entry.getValue(); + } + + params.add( resource.createFilterParam().name( key ).value( value ) ); } - resource.addFilter().name( getName() ).role( getRole() ).impl( HADOOPAUTH_FILTER_CLASSNAME ).params( params ); - resource.addFilter().name( "Post" + getName() ).role( getRole() ).impl( HADOOPAUTH_POSTFILTER_CLASSNAME ).params( params ); + + resource.addFilter().name( getName() ).role( getRole() ).impl(HADOOPAUTH_FILTER_CLASSNAME).params( params ); + resource.addFilter().name( "Post" + getName() ).role( getRole() ).impl(HADOOPAUTH_POSTFILTER_CLASSNAME).params( params ); } } http://git-wip-us.apache.org/repos/asf/knox/blob/79493c2d/gateway-provider-security-hadoopauth/src/test/java/org/apache/knox/gateway/hadoopauth/HadoopAuthDeploymentContributorTest.java ---------------------------------------------------------------------- diff --git a/gateway-provider-security-hadoopauth/src/test/java/org/apache/knox/gateway/hadoopauth/HadoopAuthDeploymentContributorTest.java b/gateway-provider-security-hadoopauth/src/test/java/org/apache/knox/gateway/hadoopauth/HadoopAuthDeploymentContributorTest.java new file mode 100644 index 0000000..7306172 --- /dev/null +++ b/gateway-provider-security-hadoopauth/src/test/java/org/apache/knox/gateway/hadoopauth/HadoopAuthDeploymentContributorTest.java @@ -0,0 +1,138 @@ +/* + * 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.knox.gateway.hadoopauth; + +import org.apache.knox.gateway.deploy.DeploymentContext; +import org.apache.knox.gateway.deploy.ProviderDeploymentContributor; +import org.apache.knox.gateway.descriptor.FilterDescriptor; +import org.apache.knox.gateway.descriptor.FilterParamDescriptor; +import org.apache.knox.gateway.descriptor.GatewayDescriptor; +import org.apache.knox.gateway.descriptor.ResourceDescriptor; +import org.apache.knox.gateway.descriptor.impl.GatewayDescriptorImpl; +import org.apache.knox.gateway.hadoopauth.deploy.HadoopAuthDeploymentContributor; +import org.apache.knox.gateway.services.GatewayServices; +import org.apache.knox.gateway.services.security.AliasService; +import org.apache.knox.gateway.services.security.impl.DefaultCryptoService; +import org.apache.knox.gateway.topology.Provider; +import org.apache.knox.gateway.topology.Topology; +import org.easymock.EasyMock; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.TreeMap; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +public class HadoopAuthDeploymentContributorTest { + + @SuppressWarnings("rawtypes") + @Test + public void testServiceLoader() { + ServiceLoader loader = ServiceLoader.load( ProviderDeploymentContributor.class ); + Iterator iterator = loader.iterator(); + assertThat( "Service iterator empty.", iterator.hasNext() ); + while( iterator.hasNext() ) { + Object object = iterator.next(); + if( object instanceof HadoopAuthDeploymentContributor) { + return; + } + } + fail( "Failed to find " + HadoopAuthDeploymentContributor.class.getName() + " via service loader." ); + } + + @Test + public void testDeployment() throws Exception { + String aliasKey = "signature.secret"; + String aliasValue = "password"; + String normalKey = "type"; + String normalValue = "simple"; + + WebArchive webArchive = ShrinkWrap.create( WebArchive.class, "test-acrhive" ); + + Provider provider = new Provider(); + provider.setEnabled( true ); + provider.setName( HadoopAuthDeploymentContributor.NAME ); + // Keep order of params in map for testing + Map<String, String> params = new TreeMap<>(); + params.put(aliasKey, aliasKey); + params.put(normalKey, normalValue); + provider.setParams(params); + + Topology topology = new Topology(); + topology.setName( "Sample" ); + + DeploymentContext context = EasyMock.createNiceMock( DeploymentContext.class ); + EasyMock.expect( context.getWebArchive() ).andReturn( webArchive ).anyTimes(); + EasyMock.expect( context.getTopology() ).andReturn( topology ).anyTimes(); + EasyMock.replay( context ); + + GatewayDescriptor gatewayDescriptor = new GatewayDescriptorImpl(); + ResourceDescriptor resource = gatewayDescriptor.createResource(); + + AliasService as = EasyMock.createNiceMock( AliasService.class ); + EasyMock.expect(as.getAliasesForCluster(context.getTopology().getName())) + .andReturn(Collections.singletonList(aliasKey)).anyTimes(); + EasyMock.expect(as.getPasswordFromAliasForCluster(context.getTopology().getName(), aliasKey)) + .andReturn(aliasValue.toCharArray()).anyTimes(); + EasyMock.replay( as ); + DefaultCryptoService cryptoService = new DefaultCryptoService(); + cryptoService.setAliasService( as ); + + GatewayServices gatewayServices = EasyMock.createNiceMock( GatewayServices.class ); + EasyMock.expect( gatewayServices.getService( GatewayServices.CRYPTO_SERVICE ) ).andReturn( cryptoService ).anyTimes(); + + HadoopAuthDeploymentContributor contributor = new HadoopAuthDeploymentContributor(); + contributor.setAliasService(as); + + assertThat( contributor.getRole(), is( HadoopAuthDeploymentContributor.ROLE ) ); + assertThat( contributor.getName(), is( HadoopAuthDeploymentContributor.NAME ) ); + + // Just make sure it doesn't blow up. + contributor.initializeContribution( context ); + + contributor.contributeFilter(context, provider, null, resource, null); + + // Just make sure it doesn't blow up. + contributor.finalizeContribution( context ); + + // Check that the params are properly setup + FilterDescriptor hadoopAuthFilterDescriptor = resource.filters().get(0); + assertNotNull(hadoopAuthFilterDescriptor); + assertEquals(HadoopAuthDeploymentContributor.NAME, hadoopAuthFilterDescriptor.name()); + List<FilterParamDescriptor> hadoopAuthFilterParams = hadoopAuthFilterDescriptor.params(); + assertEquals(2, hadoopAuthFilterParams.size()); + + FilterParamDescriptor paramDescriptor = hadoopAuthFilterParams.get(0); + assertEquals(aliasKey, paramDescriptor.name()); + assertEquals(aliasValue, paramDescriptor.value()); + + FilterParamDescriptor paramDescriptor2 = hadoopAuthFilterParams.get(1); + assertEquals(normalKey, paramDescriptor2.name()); + assertEquals(normalValue, paramDescriptor2.value()); + } +}
