Skip to content

Commit

Permalink
Merge pull request #191 from neo4j/1.1-crypt-non-local
Browse files Browse the repository at this point in the history
Added EncryptionLevel.REQUIRED_NON_LOCAL
  • Loading branch information
Zhen Li authored Jul 4, 2016
2 parents 4131f74 + 20f242b commit 80c5f1a
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
import org.neo4j.driver.v1.exceptions.ClientException;
import org.neo4j.driver.v1.exceptions.Neo4jException;

import static org.neo4j.driver.internal.util.AddressUtil.isLocalHost;
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED;
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED_NON_LOCAL;

public class InternalDriver implements Driver
{
private final ConnectionPool connections;
Expand All @@ -42,6 +46,15 @@ public InternalDriver( URI url, AuthToken authToken, Config config )
this.config = config;
}

@Override
public boolean isEncrypted()
{

Config.EncryptionLevel encryptionLevel = config.encryptionLevel();
return encryptionLevel.equals( REQUIRED ) ||
( encryptionLevel.equals( REQUIRED_NON_LOCAL ) && !isLocalHost( url.getHost() ) );
}

/**
* Establish a session
* @return a session that could be used to run {@link Session#run(String) a statement} or
Expand All @@ -63,7 +76,7 @@ public void close() throws Neo4jException
{
connections.close();
}
catch( Exception e )
catch ( Exception e )
{
throw new ClientException( "Failed to close driver.", e );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import static java.nio.ByteOrder.BIG_ENDIAN;
import static org.neo4j.driver.internal.connector.socket.SocketUtils.blockingRead;
import static org.neo4j.driver.internal.connector.socket.SocketUtils.blockingWrite;
import static org.neo4j.driver.internal.util.AddressUtil.isLocalHost;

public class SocketClient
{
Expand Down Expand Up @@ -251,6 +252,18 @@ public static ByteChannel create( String host, int port, Config config, Logger l
channel = new TLSSocketChannel( host, port, soChannel, logger, config.trustStrategy() );
break;
}
case REQUIRED_NON_LOCAL:
{
if ( isLocalHost( host ) )
{
channel = soChannel;
}
else
{
channel = new TLSSocketChannel( host, port, soChannel, logger, config.trustStrategy() );
}
break;
}
case NONE:
{
channel = soChannel;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* 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.neo4j.driver.internal.util;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class AddressUtil
{
/**
* Return true if the host provided matches "localhost" or "127.x.x.x".
*
* @param host the host name to test
* @return true if localhost, false otherwise
*/
public static boolean isLocalHost( String host )
{
try
{
// confirmed to work as desired with both "localhost" and "127.x.x.x"
return InetAddress.getByName( host ).isLoopbackAddress();
}
catch ( UnknownHostException e )
{
// if it's unknown, it's not local so we can safely return false
return false;
}
}

}
10 changes: 7 additions & 3 deletions driver/src/main/java/org/neo4j/driver/v1/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private Config( ConfigBuilder builder )
this.maxIdleConnectionPoolSize = builder.maxIdleConnectionPoolSize;
this.idleTimeBeforeConnectionTest = builder.idleTimeBeforeConnectionTest;

this.encryptionLevel = builder.encruptionLevel;
this.encryptionLevel = builder.encryptionLevel;
this.trustStrategy = builder.trustStrategy;
}

Expand Down Expand Up @@ -154,7 +154,7 @@ public static class ConfigBuilder
private int connectionPoolSize = 50;
private int maxIdleConnectionPoolSize = 10;
private long idleTimeBeforeConnectionTest = 200;
private EncryptionLevel encruptionLevel = EncryptionLevel.REQUIRED;
private EncryptionLevel encryptionLevel = EncryptionLevel.REQUIRED_NON_LOCAL;
private TrustStrategy trustStrategy = trustOnFirstUse(
new File( getProperty( "user.home" ), ".neo4j" + File.separator + "known_hosts" ) );

Expand Down Expand Up @@ -237,7 +237,7 @@ public ConfigBuilder withSessionLivenessCheckTimeout( long timeout )
*/
public ConfigBuilder withEncryptionLevel( EncryptionLevel level )
{
this.encruptionLevel = level;
this.encryptionLevel = level;
return this;
}

Expand Down Expand Up @@ -279,6 +279,10 @@ public enum EncryptionLevel
/** With this level, the driver will only connect to the server if it can do it without encryption. */
NONE,

/** With this level, the driver will only connect to the server without encryption if local but with
* encryption otherwise. */
REQUIRED_NON_LOCAL,

/** With this level, the driver will only connect to the server it if can do it with encryption. */
REQUIRED
}
Expand Down
6 changes: 6 additions & 0 deletions driver/src/main/java/org/neo4j/driver/v1/Driver.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.net.URI;

import org.neo4j.driver.v1.Config.EncryptionLevel;
import org.neo4j.driver.v1.exceptions.Neo4jException;

/**
Expand Down Expand Up @@ -71,6 +72,11 @@
*/
public interface Driver extends AutoCloseable
{
/**
* Return a flag to indicate whether or not encryption is used for this driver.
*/
boolean isEncrypted();

/**
* Establish a session
* @return a session that could be used to run {@link Session#run(String) a statement} or
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* 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.neo4j.driver.internal.util;

import org.junit.Test;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.*;
import static org.neo4j.driver.internal.util.AddressUtil.isLocalHost;

public class AddressUtilTest
{
@Test
public void shouldWorkForVariantsOfLocalHost() throws Exception
{
assertThat( isLocalHost( "localhost" ), equalTo( true ) );
assertThat( isLocalHost( "LocalHost" ), equalTo( true ) );
assertThat( isLocalHost( "LOCALHOST" ), equalTo( true ) );
assertThat( isLocalHost( "127.0.0.1" ), equalTo( true ) );
assertThat( isLocalHost( "127.5.6.7" ), equalTo( true ) );
assertThat( isLocalHost( "x" ), equalTo( false ) );
}

}
107 changes: 107 additions & 0 deletions driver/src/test/java/org/neo4j/driver/v1/integration/EncryptionIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* 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.neo4j.driver.v1.integration;

import org.junit.Rule;
import org.junit.Test;
import org.neo4j.driver.v1.*;
import org.neo4j.driver.v1.util.TestNeo4j;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.neo4j.driver.internal.util.AddressUtil.isLocalHost;
import static org.neo4j.driver.v1.Config.EncryptionLevel.NONE;
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED;
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED_NON_LOCAL;

public class EncryptionIT
{
@Rule
public TestNeo4j neo4j = new TestNeo4j();

@Test
public void shouldOperateWithNoEncryption() throws Exception
{
// Given
Driver driver = GraphDatabase.driver( neo4j.address(), Config.build().withEncryptionLevel( NONE ).toConfig() );

// Then
assertThat( driver.isEncrypted(), equalTo( false ) );

// When
Session session = driver.session();
StatementResult result = session.run( "RETURN 1" );

// Then
Record record = result.next();
int value = record.get( 0 ).asInt();
assertThat( value, equalTo( 1 ) );

// Finally
session.close();
driver.close();
}

@Test
public void shouldOperateWithRequiredNonLocalEncryption() throws Exception
{
// Given
Driver driver = GraphDatabase.driver( neo4j.address(), Config.build().withEncryptionLevel( REQUIRED_NON_LOCAL ).toConfig() );

// Then
assertThat( driver.isEncrypted(), equalTo( !isLocalHost( neo4j.host() ) ) );

// When
Session session = driver.session();
StatementResult result = session.run( "RETURN 1" );

// Then
Record record = result.next();
int value = record.get( 0 ).asInt();
assertThat( value, equalTo( 1 ) );

// Finally
session.close();
driver.close();
}

@Test
public void shouldOperateWithRequiredEncryption() throws Exception
{
// Given
Driver driver = GraphDatabase.driver( neo4j.address(), Config.build().withEncryptionLevel( REQUIRED ).toConfig() );

// Then
assertThat( driver.isEncrypted(), equalTo( true ) );

// When
Session session = driver.session();
StatementResult result = session.run( "RETURN 1" );

// Then
Record record = result.next();
int value = record.get( 0 ).asInt();
assertThat( value, equalTo( 1 ) );

// Finally
session.close();
driver.close();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ public class Neo4jRunner

public static final String NEORUN_START_ARGS = System.getProperty( "neorun.start.args" );
public static final String DEFAULT_URL = "bolt://localhost:7687";
private static final Config TEST_CONFIG = Config.build().withEncryptionLevel( Config.EncryptionLevel.NONE ).toConfig();
private Driver driver;
private Neo4jSettings currentSettings = Neo4jSettings.DEFAULT_SETTINGS;

Expand Down Expand Up @@ -106,7 +105,7 @@ private void startNeo4j() throws IOException
{
throw new IOException( "Failed to start neo4j server." );
}
driver = GraphDatabase.driver( DEFAULT_URL, TEST_CONFIG );
driver = GraphDatabase.driver( DEFAULT_URL /* default encryption REQUIRED_NON_LOCAL */ );
}

public synchronized void stopNeo4j() throws IOException
Expand Down
6 changes: 6 additions & 0 deletions driver/src/test/java/org/neo4j/driver/v1/util/TestNeo4j.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URL;

import org.neo4j.driver.v1.Driver;
Expand Down Expand Up @@ -100,6 +101,11 @@ public String address()
return Neo4jRunner.DEFAULT_URL;
}

public String host()
{
return URI.create( Neo4jRunner.DEFAULT_URL ).getHost();
}

static void clearDatabaseContents( Session session, String reason )
{
Neo4jRunner.debug( "Clearing database contents for: %s", reason );
Expand Down

0 comments on commit 80c5f1a

Please sign in to comment.