/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed 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.pentaho.di.trans.steps.ldapinput;
import static junit.framework.Assert.assertEquals;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Collection;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import org.junit.Before;
import org.junit.Test;
import org.pentaho.di.core.KettleClientEnvironment;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.logging.LogChannelInterface;
import org.pentaho.di.core.variables.VariableSpace;
import org.pentaho.di.trans.steps.ldapinput.store.CustomSocketFactory;
public class LdapSslProtocolTest {
private LogChannelInterface mockLogChannelInterface;
private VariableSpace mockVariableSpace;
private LdapMeta mockLdapMeta;
private class TestableLdapProtocol extends LdapSslProtocol {
public Hashtable<String, String> contextEnv = null;
public boolean trustAllCertificates = false;
public String trustStorePath = null;
public String trustStorePassword = null;
public TestableLdapProtocol( LogChannelInterface log, VariableSpace variableSpace, LdapMeta meta,
Collection<String> binaryAttributes ) {
super( log, variableSpace, meta, binaryAttributes );
}
@Override
protected InitialLdapContext createLdapContext( Hashtable<String, String> env ) throws NamingException {
contextEnv = env;
return null;
}
@Override
protected void configureSocketFactory( boolean trustAllCertificates, String trustStorePath,
String trustStorePassword ) throws KettleException {
this.trustAllCertificates = trustAllCertificates;
this.trustStorePath = trustStorePath;
this.trustStorePassword = trustStorePassword;
}
}
@Before
public void setup() {
mockLogChannelInterface = mock( LogChannelInterface.class );
mockVariableSpace = mock( VariableSpace.class );
mockLdapMeta = mock( LdapMeta.class );
}
@Test
public void testLdapProtocolAddsLdapPrefixIfNecessary() throws KettleException {
String hostConcrete = "host_concrete";
String portConcrete = "12345";
when( mockLdapMeta.getHost() ).thenReturn( hostConcrete );
when( mockLdapMeta.getPort() ).thenReturn( portConcrete );
when( mockLdapMeta.getDerefAliases() ).thenReturn( "always" );
when( mockLdapMeta.getReferrals() ).thenReturn( "follow" );
when( mockVariableSpace.environmentSubstitute( eq( hostConcrete ) ) ).thenReturn( hostConcrete );
when( mockVariableSpace.environmentSubstitute( eq( portConcrete ) ) ).thenReturn( portConcrete );
TestableLdapProtocol testableLdapProtocol =
new TestableLdapProtocol( mockLogChannelInterface, mockVariableSpace, mockLdapMeta, null );
testableLdapProtocol.connect( null, null );
assertEquals(
testableLdapProtocol.getConnectionPrefix() + hostConcrete + ":" + portConcrete,
testableLdapProtocol.contextEnv.get( Context.PROVIDER_URL ) );
}
@Test
public void testLdapProtocolSkipsAddingLdapPrefixIfNecessary() throws KettleException {
String hostnameConcrete = "host_concrete";
String hostConcrete = "ldaps://" + hostnameConcrete;
String portConcrete = "12345";
when( mockLdapMeta.getHost() ).thenReturn( hostConcrete );
when( mockLdapMeta.getPort() ).thenReturn( portConcrete );
when( mockLdapMeta.getDerefAliases() ).thenReturn( "always" );
when( mockLdapMeta.getReferrals() ).thenReturn( "follow" );
when( mockVariableSpace.environmentSubstitute( eq( hostConcrete ) ) ).thenReturn( hostConcrete );
when( mockVariableSpace.environmentSubstitute( eq( portConcrete ) ) ).thenReturn( portConcrete );
TestableLdapProtocol testableLdapProtocol =
new TestableLdapProtocol( mockLogChannelInterface, mockVariableSpace, mockLdapMeta, null );
testableLdapProtocol.connect( null, null );
assertEquals(
testableLdapProtocol.getConnectionPrefix() + hostnameConcrete + ":" + portConcrete,
testableLdapProtocol.contextEnv.get( Context.PROVIDER_URL ) );
}
@Test
public void testLdapProtocolSetsSsl() throws KettleException {
String hostConcrete = "host_concrete";
String portConcrete = "12345";
when( mockLdapMeta.getHost() ).thenReturn( hostConcrete );
when( mockLdapMeta.getPort() ).thenReturn( portConcrete );
when( mockLdapMeta.getDerefAliases() ).thenReturn( "always" );
when( mockLdapMeta.getReferrals() ).thenReturn( "follow" );
when( mockVariableSpace.environmentSubstitute( eq( hostConcrete ) ) ).thenReturn( hostConcrete );
when( mockVariableSpace.environmentSubstitute( eq( portConcrete ) ) ).thenReturn( portConcrete );
TestableLdapProtocol testableLdapProtocol =
new TestableLdapProtocol( mockLogChannelInterface, mockVariableSpace, mockLdapMeta, null );
testableLdapProtocol.connect( null, null );
assertEquals( "ssl", testableLdapProtocol.contextEnv.get( Context.SECURITY_PROTOCOL ) );
}
@Test
public void testLdapProtocolSetsSocketFactory() throws KettleException {
String hostConcrete = "host_concrete";
String portConcrete = "12345";
when( mockLdapMeta.getHost() ).thenReturn( hostConcrete );
when( mockLdapMeta.getPort() ).thenReturn( portConcrete );
when( mockLdapMeta.getDerefAliases() ).thenReturn( "always" );
when( mockLdapMeta.getReferrals() ).thenReturn( "follow" );
when( mockVariableSpace.environmentSubstitute( eq( hostConcrete ) ) ).thenReturn( hostConcrete );
when( mockVariableSpace.environmentSubstitute( eq( portConcrete ) ) ).thenReturn( portConcrete );
TestableLdapProtocol testableLdapProtocol =
new TestableLdapProtocol( mockLogChannelInterface, mockVariableSpace, mockLdapMeta, null );
testableLdapProtocol.connect( null, null );
assertEquals( CustomSocketFactory.class.getCanonicalName(), testableLdapProtocol.contextEnv
.get( "java.naming.ldap.factory.socket" ) );
}
@Test
public void testLdapProtocolSkipsConfiguresSocketFactoryIfNecessary() throws KettleException {
String hostConcrete = "host_concrete";
String portConcrete = "12345";
String trustStorePath = "TEST_PATH";
String trustStorePassword = "TEST_PASSWORD";
when( mockLdapMeta.getHost() ).thenReturn( hostConcrete );
when( mockLdapMeta.getPort() ).thenReturn( portConcrete );
when( mockLdapMeta.getDerefAliases() ).thenReturn( "always" );
when( mockLdapMeta.getReferrals() ).thenReturn( "follow" );
when( mockLdapMeta.isUseCertificate() ).thenReturn( false );
when( mockLdapMeta.isTrustAllCertificates() ).thenReturn( true );
when( mockLdapMeta.getTrustStorePath() ).thenReturn( trustStorePath );
when( mockLdapMeta.getTrustStorePassword() ).thenReturn( trustStorePassword );
when( mockVariableSpace.environmentSubstitute( eq( hostConcrete ) ) ).thenReturn( hostConcrete );
when( mockVariableSpace.environmentSubstitute( eq( portConcrete ) ) ).thenReturn( portConcrete );
TestableLdapProtocol testableLdapProtocol =
new TestableLdapProtocol( mockLogChannelInterface, mockVariableSpace, mockLdapMeta, null );
testableLdapProtocol.connect( null, null );
assertEquals( false, testableLdapProtocol.trustAllCertificates );
assertEquals( null, testableLdapProtocol.trustStorePath );
assertEquals( null, testableLdapProtocol.trustStorePassword );
}
@Test
public void testLdapProtocolConfiguresSocketFactoryIfNecessary() throws KettleException {
String hostConcrete = "host_concrete";
String portConcrete = "12345";
String trustStorePath = "TEST_PATH";
String trustStorePassword = "TEST_PASSWORD";
when( mockLdapMeta.getHost() ).thenReturn( hostConcrete );
when( mockLdapMeta.getPort() ).thenReturn( portConcrete );
when( mockLdapMeta.getDerefAliases() ).thenReturn( "always" );
when( mockLdapMeta.getReferrals() ).thenReturn( "follow" );
when( mockLdapMeta.isUseCertificate() ).thenReturn( true );
when( mockLdapMeta.isTrustAllCertificates() ).thenReturn( true );
when( mockLdapMeta.getTrustStorePath() ).thenReturn( trustStorePath );
when( mockLdapMeta.getTrustStorePassword() ).thenReturn( trustStorePassword );
when( mockVariableSpace.environmentSubstitute( eq( hostConcrete ) ) ).thenReturn( hostConcrete );
when( mockVariableSpace.environmentSubstitute( eq( portConcrete ) ) ).thenReturn( portConcrete );
when( mockVariableSpace.environmentSubstitute( eq( trustStorePath ) ) ).thenReturn( trustStorePath );
when( mockVariableSpace.environmentSubstitute( eq( trustStorePassword ) ) ).thenReturn( trustStorePassword );
TestableLdapProtocol testableLdapProtocol =
new TestableLdapProtocol( mockLogChannelInterface, mockVariableSpace, mockLdapMeta, null );
testableLdapProtocol.connect( null, null );
assertEquals( true, testableLdapProtocol.trustAllCertificates );
assertEquals( trustStorePath, testableLdapProtocol.trustStorePath );
assertEquals( trustStorePassword, testableLdapProtocol.trustStorePassword );
}
@Test
public void testResolvingPathVariables() throws KettleException {
String hostConcrete = "host_concrete";
String portConcrete = "12345";
String trustStorePath = "${KETTLE_SSL_PATH}";
String trustStorePathResolved = "/home/test_path";
String trustStorePassword = "TEST_PASSWORD";
when( mockLdapMeta.getHost() ).thenReturn( hostConcrete );
when( mockLdapMeta.getPort() ).thenReturn( portConcrete );
when( mockLdapMeta.getDerefAliases() ).thenReturn( "always" );
when( mockLdapMeta.getReferrals() ).thenReturn( "follow" );
when( mockLdapMeta.isUseCertificate() ).thenReturn( true );
when( mockLdapMeta.isTrustAllCertificates() ).thenReturn( true );
when( mockLdapMeta.getTrustStorePath() ).thenReturn( trustStorePath );
when( mockLdapMeta.getTrustStorePassword() ).thenReturn( trustStorePassword );
when( mockVariableSpace.environmentSubstitute( eq( hostConcrete ) ) ).thenReturn( hostConcrete );
when( mockVariableSpace.environmentSubstitute( eq( portConcrete ) ) ).thenReturn( portConcrete );
when( mockVariableSpace.environmentSubstitute( eq( trustStorePath ) ) ).thenReturn( trustStorePathResolved );
when( mockVariableSpace.environmentSubstitute( eq( trustStorePassword ) ) ).thenReturn( trustStorePassword );
KettleClientEnvironment.init();
TestableLdapProtocol testableLdapProtocol =
new TestableLdapProtocol( mockLogChannelInterface, mockVariableSpace, mockLdapMeta, null );
testableLdapProtocol.connect( null, null );
assertEquals( trustStorePathResolved, testableLdapProtocol.trustStorePath );
}
@Test
public void testResolvingPasswordVariables() throws KettleException {
String hostConcrete = "host_concrete";
String portConcrete = "12345";
String trustStorePath = "/home/test_path";
String trustStorePassword = "${PASSWORD_VARIABLE}";
String trustStorePasswordResolved = "TEST_PASSWORD_VALUE";
when( mockLdapMeta.getHost() ).thenReturn( hostConcrete );
when( mockLdapMeta.getPort() ).thenReturn( portConcrete );
when( mockLdapMeta.getDerefAliases() ).thenReturn( "always" );
when( mockLdapMeta.getReferrals() ).thenReturn( "follow" );
when( mockLdapMeta.isUseCertificate() ).thenReturn( true );
when( mockLdapMeta.isTrustAllCertificates() ).thenReturn( true );
when( mockLdapMeta.getTrustStorePath() ).thenReturn( trustStorePath );
when( mockLdapMeta.getTrustStorePassword() ).thenReturn( trustStorePassword );
when( mockVariableSpace.environmentSubstitute( eq( hostConcrete ) ) ).thenReturn( hostConcrete );
when( mockVariableSpace.environmentSubstitute( eq( portConcrete ) ) ).thenReturn( portConcrete );
when( mockVariableSpace.environmentSubstitute( eq( trustStorePath ) ) ).thenReturn( trustStorePath );
when( mockVariableSpace.environmentSubstitute( eq( trustStorePassword ) ) ).thenReturn( trustStorePasswordResolved );
KettleClientEnvironment.init();
TestableLdapProtocol testableLdapProtocol =
new TestableLdapProtocol( mockLogChannelInterface, mockVariableSpace, mockLdapMeta, null );
testableLdapProtocol.connect( null, null );
assertEquals( trustStorePasswordResolved, testableLdapProtocol.trustStorePassword );
}
@Test
public void testResolvingPasswordAndDecryptVariables() throws KettleException {
String hostConcrete = "host_concrete";
String portConcrete = "12345";
String trustStorePath = "/home/test_path";
String trustStorePassword = "${PASSWORD_VARIABLE}";
String trustStorePasswordResolved = "Encrypted 2be98afc86aa7f2e4cb79ff228dc6fa8c"; //original value 123456
when( mockLdapMeta.getHost() ).thenReturn( hostConcrete );
when( mockLdapMeta.getPort() ).thenReturn( portConcrete );
when( mockLdapMeta.getDerefAliases() ).thenReturn( "always" );
when( mockLdapMeta.getReferrals() ).thenReturn( "follow" );
when( mockLdapMeta.isUseCertificate() ).thenReturn( true );
when( mockLdapMeta.isTrustAllCertificates() ).thenReturn( true );
when( mockLdapMeta.getTrustStorePath() ).thenReturn( trustStorePath );
when( mockLdapMeta.getTrustStorePassword() ).thenReturn( trustStorePassword );
when( mockVariableSpace.environmentSubstitute( eq( hostConcrete ) ) ).thenReturn( hostConcrete );
when( mockVariableSpace.environmentSubstitute( eq( portConcrete ) ) ).thenReturn( portConcrete );
when( mockVariableSpace.environmentSubstitute( eq( trustStorePath ) ) ).thenReturn( trustStorePath );
when( mockVariableSpace.environmentSubstitute( eq( trustStorePassword ) ) ).thenReturn( trustStorePasswordResolved );
KettleClientEnvironment.init();
TestableLdapProtocol testableLdapProtocol =
new TestableLdapProtocol( mockLogChannelInterface, mockVariableSpace, mockLdapMeta, null );
testableLdapProtocol.connect( null, null );
assertEquals( "123456", testableLdapProtocol.trustStorePassword );
}
}