Skip to content

Commit 80c5f1a

Browse files
author
Zhen Li
authored
Merge pull request #191 from neo4j/1.1-crypt-non-local
Added EncryptionLevel.REQUIRED_NON_LOCAL
2 parents 4131f74 + 20f242b commit 80c5f1a

File tree

9 files changed

+241
-6
lines changed

9 files changed

+241
-6
lines changed

driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
import org.neo4j.driver.v1.exceptions.ClientException;
3030
import org.neo4j.driver.v1.exceptions.Neo4jException;
3131

32+
import static org.neo4j.driver.internal.util.AddressUtil.isLocalHost;
33+
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED;
34+
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED_NON_LOCAL;
35+
3236
public class InternalDriver implements Driver
3337
{
3438
private final ConnectionPool connections;
@@ -42,6 +46,15 @@ public InternalDriver( URI url, AuthToken authToken, Config config )
4246
this.config = config;
4347
}
4448

49+
@Override
50+
public boolean isEncrypted()
51+
{
52+
53+
Config.EncryptionLevel encryptionLevel = config.encryptionLevel();
54+
return encryptionLevel.equals( REQUIRED ) ||
55+
( encryptionLevel.equals( REQUIRED_NON_LOCAL ) && !isLocalHost( url.getHost() ) );
56+
}
57+
4558
/**
4659
* Establish a session
4760
* @return a session that could be used to run {@link Session#run(String) a statement} or
@@ -63,7 +76,7 @@ public void close() throws Neo4jException
6376
{
6477
connections.close();
6578
}
66-
catch( Exception e )
79+
catch ( Exception e )
6780
{
6881
throw new ClientException( "Failed to close driver.", e );
6982
}

driver/src/main/java/org/neo4j/driver/internal/connector/socket/SocketClient.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import static java.nio.ByteOrder.BIG_ENDIAN;
3939
import static org.neo4j.driver.internal.connector.socket.SocketUtils.blockingRead;
4040
import static org.neo4j.driver.internal.connector.socket.SocketUtils.blockingWrite;
41+
import static org.neo4j.driver.internal.util.AddressUtil.isLocalHost;
4142

4243
public class SocketClient
4344
{
@@ -251,6 +252,18 @@ public static ByteChannel create( String host, int port, Config config, Logger l
251252
channel = new TLSSocketChannel( host, port, soChannel, logger, config.trustStrategy() );
252253
break;
253254
}
255+
case REQUIRED_NON_LOCAL:
256+
{
257+
if ( isLocalHost( host ) )
258+
{
259+
channel = soChannel;
260+
}
261+
else
262+
{
263+
channel = new TLSSocketChannel( host, port, soChannel, logger, config.trustStrategy() );
264+
}
265+
break;
266+
}
254267
case NONE:
255268
{
256269
channel = soChannel;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright (c) 2002-2016 "Neo Technology,"
3+
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
package org.neo4j.driver.internal.util;
21+
22+
import java.net.InetAddress;
23+
import java.net.UnknownHostException;
24+
25+
public class AddressUtil
26+
{
27+
/**
28+
* Return true if the host provided matches "localhost" or "127.x.x.x".
29+
*
30+
* @param host the host name to test
31+
* @return true if localhost, false otherwise
32+
*/
33+
public static boolean isLocalHost( String host )
34+
{
35+
try
36+
{
37+
// confirmed to work as desired with both "localhost" and "127.x.x.x"
38+
return InetAddress.getByName( host ).isLoopbackAddress();
39+
}
40+
catch ( UnknownHostException e )
41+
{
42+
// if it's unknown, it's not local so we can safely return false
43+
return false;
44+
}
45+
}
46+
47+
}

driver/src/main/java/org/neo4j/driver/v1/Config.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private Config( ConfigBuilder builder )
7070
this.maxIdleConnectionPoolSize = builder.maxIdleConnectionPoolSize;
7171
this.idleTimeBeforeConnectionTest = builder.idleTimeBeforeConnectionTest;
7272

73-
this.encryptionLevel = builder.encruptionLevel;
73+
this.encryptionLevel = builder.encryptionLevel;
7474
this.trustStrategy = builder.trustStrategy;
7575
}
7676

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

@@ -237,7 +237,7 @@ public ConfigBuilder withSessionLivenessCheckTimeout( long timeout )
237237
*/
238238
public ConfigBuilder withEncryptionLevel( EncryptionLevel level )
239239
{
240-
this.encruptionLevel = level;
240+
this.encryptionLevel = level;
241241
return this;
242242
}
243243

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

282+
/** With this level, the driver will only connect to the server without encryption if local but with
283+
* encryption otherwise. */
284+
REQUIRED_NON_LOCAL,
285+
282286
/** With this level, the driver will only connect to the server it if can do it with encryption. */
283287
REQUIRED
284288
}

driver/src/main/java/org/neo4j/driver/v1/Driver.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.net.URI;
2222

23+
import org.neo4j.driver.v1.Config.EncryptionLevel;
2324
import org.neo4j.driver.v1.exceptions.Neo4jException;
2425

2526
/**
@@ -71,6 +72,11 @@
7172
*/
7273
public interface Driver extends AutoCloseable
7374
{
75+
/**
76+
* Return a flag to indicate whether or not encryption is used for this driver.
77+
*/
78+
boolean isEncrypted();
79+
7480
/**
7581
* Establish a session
7682
* @return a session that could be used to run {@link Session#run(String) a statement} or
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright (c) 2002-2016 "Neo Technology,"
3+
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.internal.util;
20+
21+
import org.junit.Test;
22+
23+
import static org.hamcrest.CoreMatchers.equalTo;
24+
import static org.junit.Assert.*;
25+
import static org.neo4j.driver.internal.util.AddressUtil.isLocalHost;
26+
27+
public class AddressUtilTest
28+
{
29+
@Test
30+
public void shouldWorkForVariantsOfLocalHost() throws Exception
31+
{
32+
assertThat( isLocalHost( "localhost" ), equalTo( true ) );
33+
assertThat( isLocalHost( "LocalHost" ), equalTo( true ) );
34+
assertThat( isLocalHost( "LOCALHOST" ), equalTo( true ) );
35+
assertThat( isLocalHost( "127.0.0.1" ), equalTo( true ) );
36+
assertThat( isLocalHost( "127.5.6.7" ), equalTo( true ) );
37+
assertThat( isLocalHost( "x" ), equalTo( false ) );
38+
}
39+
40+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/**
2+
* Copyright (c) 2002-2016 "Neo Technology,"
3+
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.v1.integration;
20+
21+
import org.junit.Rule;
22+
import org.junit.Test;
23+
import org.neo4j.driver.v1.*;
24+
import org.neo4j.driver.v1.util.TestNeo4j;
25+
26+
import static org.hamcrest.CoreMatchers.equalTo;
27+
import static org.hamcrest.MatcherAssert.assertThat;
28+
import static org.neo4j.driver.internal.util.AddressUtil.isLocalHost;
29+
import static org.neo4j.driver.v1.Config.EncryptionLevel.NONE;
30+
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED;
31+
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED_NON_LOCAL;
32+
33+
public class EncryptionIT
34+
{
35+
@Rule
36+
public TestNeo4j neo4j = new TestNeo4j();
37+
38+
@Test
39+
public void shouldOperateWithNoEncryption() throws Exception
40+
{
41+
// Given
42+
Driver driver = GraphDatabase.driver( neo4j.address(), Config.build().withEncryptionLevel( NONE ).toConfig() );
43+
44+
// Then
45+
assertThat( driver.isEncrypted(), equalTo( false ) );
46+
47+
// When
48+
Session session = driver.session();
49+
StatementResult result = session.run( "RETURN 1" );
50+
51+
// Then
52+
Record record = result.next();
53+
int value = record.get( 0 ).asInt();
54+
assertThat( value, equalTo( 1 ) );
55+
56+
// Finally
57+
session.close();
58+
driver.close();
59+
}
60+
61+
@Test
62+
public void shouldOperateWithRequiredNonLocalEncryption() throws Exception
63+
{
64+
// Given
65+
Driver driver = GraphDatabase.driver( neo4j.address(), Config.build().withEncryptionLevel( REQUIRED_NON_LOCAL ).toConfig() );
66+
67+
// Then
68+
assertThat( driver.isEncrypted(), equalTo( !isLocalHost( neo4j.host() ) ) );
69+
70+
// When
71+
Session session = driver.session();
72+
StatementResult result = session.run( "RETURN 1" );
73+
74+
// Then
75+
Record record = result.next();
76+
int value = record.get( 0 ).asInt();
77+
assertThat( value, equalTo( 1 ) );
78+
79+
// Finally
80+
session.close();
81+
driver.close();
82+
}
83+
84+
@Test
85+
public void shouldOperateWithRequiredEncryption() throws Exception
86+
{
87+
// Given
88+
Driver driver = GraphDatabase.driver( neo4j.address(), Config.build().withEncryptionLevel( REQUIRED ).toConfig() );
89+
90+
// Then
91+
assertThat( driver.isEncrypted(), equalTo( true ) );
92+
93+
// When
94+
Session session = driver.session();
95+
StatementResult result = session.run( "RETURN 1" );
96+
97+
// Then
98+
Record record = result.next();
99+
int value = record.get( 0 ).asInt();
100+
assertThat( value, equalTo( 1 ) );
101+
102+
// Finally
103+
session.close();
104+
driver.close();
105+
}
106+
107+
}

driver/src/test/java/org/neo4j/driver/v1/util/Neo4jRunner.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ public class Neo4jRunner
4545

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

@@ -106,7 +105,7 @@ private void startNeo4j() throws IOException
106105
{
107106
throw new IOException( "Failed to start neo4j server." );
108107
}
109-
driver = GraphDatabase.driver( DEFAULT_URL, TEST_CONFIG );
108+
driver = GraphDatabase.driver( DEFAULT_URL /* default encryption REQUIRED_NON_LOCAL */ );
110109
}
111110

112111
public synchronized void stopNeo4j() throws IOException

driver/src/test/java/org/neo4j/driver/v1/util/TestNeo4j.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.io.File;
2626
import java.io.IOException;
2727
import java.io.PrintWriter;
28+
import java.net.URI;
2829
import java.net.URL;
2930

3031
import org.neo4j.driver.v1.Driver;
@@ -100,6 +101,11 @@ public String address()
100101
return Neo4jRunner.DEFAULT_URL;
101102
}
102103

104+
public String host()
105+
{
106+
return URI.create( Neo4jRunner.DEFAULT_URL ).getHost();
107+
}
108+
103109
static void clearDatabaseContents( Session session, String reason )
104110
{
105111
Neo4jRunner.debug( "Clearing database contents for: %s", reason );

0 commit comments

Comments
 (0)