From a0f5b077073b989962040ea28e7f18781fb7ed3f Mon Sep 17 00:00:00 2001
From: Dmitriy Tverdiakov <11927660+injectives@users.noreply.github.com>
Date: Tue, 20 Dec 2022 10:35:50 +0000
Subject: [PATCH] Add 2 access options to Config and refactor DriverFactory
(#1356)
This update adds 2 getters for existing configuration options in `Config`:
- `routingTablePurgeDelayMillis()` - provides access to value configured via `ConfigBuilder.withRoutingTablePurgeDelay(long, TimeUnit)`
- `maxTransactionRetryTimeMillis()` - provides access to value configured via `ConfigBuilder.withMaxTransactionRetryTime(long, TimeUnit)`
It also includes internal `DriverFactory` refactoring.
---
.../main/java/org/neo4j/driver/Config.java | 83 ++++---
.../java/org/neo4j/driver/GraphDatabase.java | 10 +-
.../neo4j/driver/internal/DriverFactory.java | 36 +--
.../driver/internal/SecuritySettings.java | 85 +-------
.../internal/cluster/RoutingSettings.java | 5 -
.../retry/ExponentialBackoffRetryLogic.java | 6 +-
.../internal/security/SecurityPlans.java | 108 +++++++++
.../java/org/neo4j/driver/ConfigTest.java | 42 +++-
.../integration/ConnectionHandlingIT.java | 11 +-
.../driver/integration/ConnectionPoolIT.java | 4 +-
.../org/neo4j/driver/integration/ErrorIT.java | 8 +-
.../driver/integration/ServerKilledIT.java | 7 +-
.../driver/integration/SessionBoltV3IT.java | 9 +-
.../neo4j/driver/integration/SessionIT.java | 9 +-
.../driver/integration/SharedEventLoopIT.java | 6 +-
.../driver/integration/TransactionIT.java | 9 +-
.../integration/UnmanagedTransactionIT.java | 9 +-
.../internal/CustomSecurityPlanTest.java | 6 +-
.../driver/internal/DriverFactoryTest.java | 27 +--
.../driver/internal/SecuritySettingsTest.java | 191 +---------------
.../ExponentialBackoffRetryLogicTest.java | 46 ++--
.../internal/security/SecurityPlans.java | 205 ++++++++++++++++++
.../DriverFactoryWithFixedRetryLogic.java | 3 +-
.../driver/internal/util/FixedRetryLogic.java | 3 +-
.../backend/messages/requests/NewDriver.java | 16 +-
25 files changed, 462 insertions(+), 482 deletions(-)
create mode 100644 driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlans.java
create mode 100644 driver/src/test/java/org/neo4j/driver/internal/security/SecurityPlans.java
diff --git a/driver/src/main/java/org/neo4j/driver/Config.java b/driver/src/main/java/org/neo4j/driver/Config.java
index 9e7aa774b3..45746cbe62 100644
--- a/driver/src/main/java/org/neo4j/driver/Config.java
+++ b/driver/src/main/java/org/neo4j/driver/Config.java
@@ -36,7 +36,7 @@
import org.neo4j.driver.internal.async.pool.PoolSettings;
import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.handlers.pulln.FetchSizeUtil;
-import org.neo4j.driver.internal.retry.RetrySettings;
+import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic;
import org.neo4j.driver.net.ServerAddressResolver;
import org.neo4j.driver.util.Experimental;
import org.neo4j.driver.util.Immutable;
@@ -75,7 +75,9 @@ public final class Config implements Serializable {
private static final Config EMPTY = builder().build();
- /** User defined logging */
+ /**
+ * User defined logging
+ */
private final Logging logging;
private final boolean logLeakedSessions;
@@ -90,9 +92,9 @@ public final class Config implements Serializable {
private final long fetchSize;
private final long routingTablePurgeDelayMillis;
+ private final long maxTransactionRetryTimeMillis;
private final int connectionTimeoutMillis;
- private final RetrySettings retrySettings;
private final ServerAddressResolver resolver;
private final int eventLoopThreads;
@@ -113,7 +115,7 @@ private Config(ConfigBuilder builder) {
this.connectionTimeoutMillis = builder.connectionTimeoutMillis;
this.routingTablePurgeDelayMillis = builder.routingTablePurgeDelayMillis;
- this.retrySettings = builder.retrySettings;
+ this.maxTransactionRetryTimeMillis = builder.maxTransactionRetryTimeMillis;
this.resolver = builder.resolver;
this.fetchSize = builder.fetchSize;
@@ -123,6 +125,7 @@ private Config(ConfigBuilder builder) {
/**
* Logging provider
+ *
* @return the Logging provider to use
*/
public Logging logging() {
@@ -212,18 +215,21 @@ public static Config defaultConfig() {
}
/**
- * @return the security setting to use when creating connections.
+ * Returns stale routing table purge delay.
+ *
+ * @return routing table purge delay
*/
- SecuritySettings securitySettings() {
- return securitySettings;
+ public long routingTablePurgeDelayMillis() {
+ return routingTablePurgeDelayMillis;
}
- RoutingSettings routingSettings() {
- return new RoutingSettings(routingTablePurgeDelayMillis);
- }
-
- RetrySettings retrySettings() {
- return retrySettings;
+ /**
+ * Returns managed transactions maximum retry time.
+ *
+ * @return maximum retry time
+ */
+ public long maxTransactionRetryTimeMillis() {
+ return maxTransactionRetryTimeMillis;
}
public long fetchSize() {
@@ -265,9 +271,9 @@ public static final class ConfigBuilder {
private String userAgent = format("neo4j-java/%s", driverVersion());
private final SecuritySettings.SecuritySettingsBuilder securitySettingsBuilder =
new SecuritySettings.SecuritySettingsBuilder();
- private long routingTablePurgeDelayMillis = RoutingSettings.DEFAULT.routingTablePurgeDelayMs();
+ private long routingTablePurgeDelayMillis = RoutingSettings.STALE_ROUTING_TABLE_PURGE_DELAY_MS;
private int connectionTimeoutMillis = (int) TimeUnit.SECONDS.toMillis(30);
- private RetrySettings retrySettings = RetrySettings.DEFAULT;
+ private long maxTransactionRetryTimeMillis = ExponentialBackoffRetryLogic.DEFAULT_MAX_RETRY_TIME_MS;
private ServerAddressResolver resolver;
private MetricsAdapter metricsAdapter = MetricsAdapter.DEV_NULL;
private long fetchSize = FetchSizeUtil.DEFAULT_FETCH_SIZE;
@@ -331,7 +337,7 @@ public ConfigBuilder withLeakedSessionsLogging() {
* validity and negative values mean connections will never be tested.
*
* @param value the minimum idle time
- * @param unit the unit in which the duration is given
+ * @param unit the unit in which the duration is given
* @return this builder
*/
public ConfigBuilder withConnectionLivenessCheckTimeout(long value, TimeUnit unit) {
@@ -356,7 +362,7 @@ public ConfigBuilder withConnectionLivenessCheckTimeout(long value, TimeUnit uni
* checked.
*
* @param value the maximum connection lifetime
- * @param unit the unit in which the duration is given
+ * @param unit the unit in which the duration is given
* @return this builder
*/
public ConfigBuilder withMaxConnectionLifetime(long value, TimeUnit unit) {
@@ -402,7 +408,7 @@ public ConfigBuilder withMaxConnectionPoolSize(int value) {
* of {@code 0} is allowed and results in no timeout and immediate failure when connection is unavailable.
*
* @param value the acquisition timeout
- * @param unit the unit in which the duration is given
+ * @param unit the unit in which the duration is given
* @return this builder
* @see #withMaxConnectionPoolSize(int)
*/
@@ -418,6 +424,7 @@ public ConfigBuilder withConnectionAcquisitionTimeout(long value, TimeUnit unit)
/**
* Set to use encrypted traffic.
+ *
* @return this builder
*/
public ConfigBuilder withEncryption() {
@@ -427,6 +434,7 @@ public ConfigBuilder withEncryption() {
/**
* Set to use unencrypted traffic.
+ *
* @return this builder
*/
public ConfigBuilder withoutEncryption() {
@@ -461,13 +469,12 @@ public ConfigBuilder withTrustStrategy(TrustStrategy trustStrategy) {
* The routing table of a database get refreshed if the database is used frequently.
* If the database is not used for a long time,
* the driver use the timeout specified here to purge the stale routing table.
- *
+ *
* After a routing table is removed, next time when using the database of the purged routing table,
* the driver will fall back to use seed URI for a new routing table.
- * @param delay
- * the amount of time to wait before purging routing tables
- * @param unit
- * the unit in which the duration is given
+ *
+ * @param delay the amount of time to wait before purging routing tables
+ * @param unit the unit in which the duration is given
* @return this builder
*/
public ConfigBuilder withRoutingTablePurgeDelay(long delay, TimeUnit unit) {
@@ -483,15 +490,16 @@ public ConfigBuilder withRoutingTablePurgeDelay(long delay, TimeUnit unit) {
/**
* Specify how many records to fetch in each batch.
* This config is only valid when the driver is used with servers that support Bolt V4 (Server version 4.0 and later).
- *
+ *
* Bolt V4 enables pulling records in batches to allow client to take control of data population and apply back pressure to server.
* This config specifies the default fetch size for all query runs using {@link Session} and {@link org.neo4j.driver.async.AsyncSession}.
* By default, the value is set to {@code 1000}.
* Use {@code -1} to disables back pressure and config client to pull all records at once after each run.
- *
+ *
* This config only applies to run result obtained via {@link Session} and {@link org.neo4j.driver.async.AsyncSession}.
* As with {@link org.neo4j.driver.reactive.RxSession}, the batch size is provided via
* {@link org.reactivestreams.Subscription#request(long)} instead.
+ *
* @param size the default record fetch size when pulling records in batches using Bolt V4.
* @return this builder
*/
@@ -512,10 +520,10 @@ public ConfigBuilder withFetchSize(long size) {
* The default value of this parameter is {@code 30 SECONDS}.
*
* @param value the timeout duration
- * @param unit the unit in which duration is given
+ * @param unit the unit in which duration is given
* @return this builder
* @throws IllegalArgumentException when given value is negative or does not fit in {@code int} when
- * converted to milliseconds.
+ * converted to milliseconds.
*/
public ConfigBuilder withConnectionTimeout(long value, TimeUnit unit) {
long connectionTimeoutMillis = unit.toMillis(value);
@@ -534,16 +542,14 @@ public ConfigBuilder withConnectionTimeout(long value, TimeUnit unit) {
}
/**
- * Specify the maximum time transactions are allowed to retry via
- * {@link Session#readTransaction(TransactionWork)} and {@link Session#writeTransaction(TransactionWork)}
- * methods. These methods will retry the given unit of work on {@link org.neo4j.driver.exceptions.ServiceUnavailableException},
- * {@link org.neo4j.driver.exceptions.SessionExpiredException} and {@link org.neo4j.driver.exceptions.TransientException} with
- * exponential backoff using initial delay of 1 second.
+ * Specify the maximum time managed transactions are allowed to retry.
+ *
+ * Managed transactions are available via methods like {@link Session#executeRead(TransactionCallback)}, {@link Session#executeWrite(TransactionCallback, TransactionConfig)} and some other variations available under similar naming.
*
* Default value is 30 seconds.
*
* @param value the timeout duration
- * @param unit the unit in which duration is given
+ * @param unit the unit in which duration is given
* @return this builder
* @throws IllegalArgumentException when given value is negative
*/
@@ -553,7 +559,7 @@ public ConfigBuilder withMaxTransactionRetryTime(long value, TimeUnit unit) {
throw new IllegalArgumentException(
String.format("The max retry time may not be smaller than 0, but was %d %s.", value, unit));
}
- this.retrySettings = new RetrySettings(maxRetryTimeMs);
+ this.maxTransactionRetryTimeMillis = maxRetryTimeMs;
return this;
}
@@ -586,6 +592,7 @@ public ConfigBuilder withDriverMetrics() {
/**
* Disable driver metrics. When disabled, driver metrics cannot be accessed via {@link Driver#metrics()}.
+ *
* @return this builder.
*/
public ConfigBuilder withoutDriverMetrics() {
@@ -619,6 +626,7 @@ public ConfigBuilder withMetricsAdapter(MetricsAdapter metricsAdapter) {
/**
* Configure the event loop thread count. This specifies how many threads the driver can use to handle network I/O events
* and user's events in driver's I/O threads. By default, 2 * NumberOfProcessors amount of threads will be used instead.
+ *
* @param size the thread count.
* @return this builder.
* @throws IllegalArgumentException if the value of the size is set to a number that is less than 1.
@@ -634,6 +642,7 @@ public ConfigBuilder withEventLoopThreads(int size) {
/**
* Configure the user_agent field sent to the server to identify the connected client.
+ *
* @param userAgent the string to configure user_agent.
* @return this builder.
*/
@@ -802,6 +811,7 @@ public static TrustStrategy trustAllCertificates() {
/**
* The revocation strategy used for verifying certificates.
+ *
* @return this {@link TrustStrategy}'s revocation strategy
*/
public RevocationCheckingStrategy revocationCheckingStrategy() {
@@ -811,6 +821,7 @@ public RevocationCheckingStrategy revocationCheckingStrategy() {
/**
* Configures the {@link TrustStrategy} to not carry out OCSP revocation checks on certificates. This is the
* option that is configured by default.
+ *
* @return the current trust strategy
*/
public TrustStrategy withoutCertificateRevocationChecks() {
@@ -823,6 +834,7 @@ public TrustStrategy withoutCertificateRevocationChecks() {
* stapled to the certificate. If no stapled response is found, then certificate verification continues
* (and does not fail verification). This setting also requires the server to be configured to enable
* OCSP stapling.
+ *
* @return the current trust strategy
*/
public TrustStrategy withVerifyIfPresentRevocationChecks() {
@@ -834,9 +846,10 @@ public TrustStrategy withVerifyIfPresentRevocationChecks() {
* Configures the {@link TrustStrategy} to carry out strict OCSP revocation checks for revocation status that
* are stapled to the certificate. If no stapled response is found, then the driver will fail certificate verification
* and not connect to the server. This setting also requires the server to be configured to enable OCSP stapling.
- *
+ *
* Note: enabling this setting will prevent the driver connecting to the server when the server is unable to reach
* the certificate's configured OCSP responder URL.
+ *
* @return the current trust strategy
*/
public TrustStrategy withStrictRevocationChecks() {
diff --git a/driver/src/main/java/org/neo4j/driver/GraphDatabase.java b/driver/src/main/java/org/neo4j/driver/GraphDatabase.java
index ca0ea494d6..3c564c0c59 100644
--- a/driver/src/main/java/org/neo4j/driver/GraphDatabase.java
+++ b/driver/src/main/java/org/neo4j/driver/GraphDatabase.java
@@ -20,10 +20,6 @@
import java.net.URI;
import org.neo4j.driver.internal.DriverFactory;
-import org.neo4j.driver.internal.SecuritySettings;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
-import org.neo4j.driver.internal.retry.RetrySettings;
-import org.neo4j.driver.internal.security.SecurityPlan;
/**
* Creates {@link Driver drivers}, optionally letting you {@link #driver(URI, Config)} to configure them.
@@ -123,11 +119,7 @@ public static Driver driver(URI uri, AuthToken authToken, Config config) {
static Driver driver(URI uri, AuthToken authToken, Config config, DriverFactory driverFactory) {
config = getOrDefault(config);
- RoutingSettings routingSettings = config.routingSettings();
- RetrySettings retrySettings = config.retrySettings();
- SecuritySettings securitySettings = config.securitySettings();
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(uri.getScheme());
- return driverFactory.newInstance(uri, authToken, routingSettings, retrySettings, config, securityPlan);
+ return driverFactory.newInstance(uri, authToken, config);
}
private static Config getOrDefault(Config config) {
diff --git a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java
index 25d7e00af1..c10d586c96 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java
@@ -55,8 +55,8 @@
import org.neo4j.driver.internal.metrics.MicrometerMetricsProvider;
import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic;
import org.neo4j.driver.internal.retry.RetryLogic;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlan;
+import org.neo4j.driver.internal.security.SecurityPlans;
import org.neo4j.driver.internal.spi.ConnectionPool;
import org.neo4j.driver.internal.spi.ConnectionProvider;
import org.neo4j.driver.internal.util.Clock;
@@ -67,25 +67,18 @@ public class DriverFactory {
public static final String NO_ROUTING_CONTEXT_ERROR_MESSAGE =
"Routing parameters are not supported with scheme 'bolt'. Given URI: ";
- public final Driver newInstance(
- URI uri,
- AuthToken authToken,
- RoutingSettings routingSettings,
- RetrySettings retrySettings,
- Config config,
- SecurityPlan securityPlan) {
- return newInstance(uri, authToken, routingSettings, retrySettings, config, null, securityPlan, null);
+ public final Driver newInstance(URI uri, AuthToken authToken, Config config) {
+ return newInstance(uri, authToken, config, null, null, null);
}
public final Driver newInstance(
URI uri,
AuthToken authToken,
- RoutingSettings routingSettings,
- RetrySettings retrySettings,
Config config,
- EventLoopGroup eventLoopGroup,
SecurityPlan securityPlan,
+ EventLoopGroup eventLoopGroup,
Supplier rediscoverySupplier) {
+
Bootstrap bootstrap;
boolean ownsEventLoopGroup;
if (eventLoopGroup == null) {
@@ -96,14 +89,21 @@ public final Driver newInstance(
ownsEventLoopGroup = false;
}
+ if (securityPlan == null) {
+ var settings = new SecuritySettings(config.encrypted(), config.trustStrategy());
+ securityPlan = SecurityPlans.createSecurityPlan(settings, uri.getScheme());
+ }
+
authToken = authToken == null ? AuthTokens.none() : authToken;
BoltServerAddress address = new BoltServerAddress(uri);
- RoutingSettings newRoutingSettings = routingSettings.withRoutingContext(new RoutingContext(uri));
+ RoutingSettings routingSettings =
+ new RoutingSettings(config.routingTablePurgeDelayMillis(), new RoutingContext(uri));
InternalLoggerFactory.setDefaultFactory(new NettyLogging(config.logging()));
EventExecutorGroup eventExecutorGroup = bootstrap.config().group();
- RetryLogic retryLogic = createRetryLogic(retrySettings, eventExecutorGroup, config.logging());
+ RetryLogic retryLogic =
+ createRetryLogic(config.maxTransactionRetryTimeMillis(), eventExecutorGroup, config.logging());
MetricsProvider metricsProvider = getOrCreateMetricsProvider(config, createClock());
ConnectionPool connectionPool = createConnectionPool(
@@ -113,7 +113,7 @@ public final Driver newInstance(
metricsProvider,
config,
ownsEventLoopGroup,
- newRoutingSettings.routingContext());
+ routingSettings.routingContext());
return createDriver(
uri,
@@ -121,7 +121,7 @@ public final Driver newInstance(
address,
connectionPool,
eventExecutorGroup,
- newRoutingSettings,
+ routingSettings,
retryLogic,
metricsProvider,
rediscoverySupplier,
@@ -354,8 +354,8 @@ protected SessionFactory createSessionFactory(
* This method is protected only for testing
*/
protected RetryLogic createRetryLogic(
- RetrySettings settings, EventExecutorGroup eventExecutorGroup, Logging logging) {
- return new ExponentialBackoffRetryLogic(settings, eventExecutorGroup, createClock(), logging);
+ long maxTransactionRetryTime, EventExecutorGroup eventExecutorGroup, Logging logging) {
+ return new ExponentialBackoffRetryLogic(maxTransactionRetryTime, eventExecutorGroup, createClock(), logging);
}
/**
diff --git a/driver/src/main/java/org/neo4j/driver/internal/SecuritySettings.java b/driver/src/main/java/org/neo4j/driver/internal/SecuritySettings.java
index c86daeeb88..2d83716413 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/SecuritySettings.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/SecuritySettings.java
@@ -18,25 +18,15 @@
*/
package org.neo4j.driver.internal;
-import static org.neo4j.driver.internal.Scheme.isHighTrustScheme;
-import static org.neo4j.driver.internal.Scheme.isSecurityScheme;
-import static org.neo4j.driver.internal.security.SecurityPlanImpl.insecure;
-
-import java.io.IOException;
import java.io.Serializable;
-import java.security.GeneralSecurityException;
import org.neo4j.driver.Config;
-import org.neo4j.driver.RevocationCheckingStrategy;
-import org.neo4j.driver.exceptions.ClientException;
-import org.neo4j.driver.internal.security.SecurityPlan;
-import org.neo4j.driver.internal.security.SecurityPlanImpl;
public class SecuritySettings implements Serializable {
private static final long serialVersionUID = 4494615367164106576L;
private static final boolean DEFAULT_ENCRYPTED = false;
private static final Config.TrustStrategy DEFAULT_TRUST_STRATEGY = Config.TrustStrategy.trustSystemCertificates();
- private static final SecuritySettings DEFAULT = new SecuritySettings(DEFAULT_ENCRYPTED, DEFAULT_TRUST_STRATEGY);
+ public static final SecuritySettings DEFAULT = new SecuritySettings(DEFAULT_ENCRYPTED, DEFAULT_TRUST_STRATEGY);
private final boolean encrypted;
private final Config.TrustStrategy trustStrategy;
@@ -53,79 +43,6 @@ public Config.TrustStrategy trustStrategy() {
return trustStrategy;
}
- private boolean isCustomized() {
- return !(DEFAULT.encrypted() == this.encrypted() && DEFAULT.hasEqualTrustStrategy(this));
- }
-
- private boolean hasEqualTrustStrategy(SecuritySettings other) {
- Config.TrustStrategy t1 = this.trustStrategy;
- Config.TrustStrategy t2 = other.trustStrategy;
- if (t1 == t2) {
- return true;
- }
-
- return t1.isHostnameVerificationEnabled() == t2.isHostnameVerificationEnabled()
- && t1.strategy() == t2.strategy()
- && t1.certFiles().equals(t2.certFiles())
- && t1.revocationCheckingStrategy() == t2.revocationCheckingStrategy();
- }
-
- public SecurityPlan createSecurityPlan(String uriScheme) {
- Scheme.validateScheme(uriScheme);
- try {
- if (isSecurityScheme(uriScheme)) {
- assertSecuritySettingsNotUserConfigured(uriScheme);
- return createSecurityPlanFromScheme(uriScheme);
- } else {
- return createSecurityPlanImpl(encrypted, trustStrategy);
- }
- } catch (GeneralSecurityException | IOException ex) {
- throw new ClientException("Unable to establish SSL parameters", ex);
- }
- }
-
- private void assertSecuritySettingsNotUserConfigured(String uriScheme) {
- if (isCustomized()) {
- throw new ClientException(String.format(
- "Scheme %s is not configurable with manual encryption and trust settings", uriScheme));
- }
- }
-
- private SecurityPlan createSecurityPlanFromScheme(String scheme) throws GeneralSecurityException, IOException {
- if (isHighTrustScheme(scheme)) {
- return SecurityPlanImpl.forSystemCASignedCertificates(true, RevocationCheckingStrategy.NO_CHECKS);
- } else {
- return SecurityPlanImpl.forAllCertificates(false, RevocationCheckingStrategy.NO_CHECKS);
- }
- }
-
- /*
- * Establish a complete SecurityPlan based on the details provided for
- * driver construction.
- */
- private static SecurityPlan createSecurityPlanImpl(boolean encrypted, Config.TrustStrategy trustStrategy)
- throws GeneralSecurityException, IOException {
- if (encrypted) {
- boolean hostnameVerificationEnabled = trustStrategy.isHostnameVerificationEnabled();
- RevocationCheckingStrategy revocationCheckingStrategy = trustStrategy.revocationCheckingStrategy();
- switch (trustStrategy.strategy()) {
- case TRUST_CUSTOM_CA_SIGNED_CERTIFICATES:
- return SecurityPlanImpl.forCustomCASignedCertificates(
- trustStrategy.certFiles(), hostnameVerificationEnabled, revocationCheckingStrategy);
- case TRUST_SYSTEM_CA_SIGNED_CERTIFICATES:
- return SecurityPlanImpl.forSystemCASignedCertificates(
- hostnameVerificationEnabled, revocationCheckingStrategy);
- case TRUST_ALL_CERTIFICATES:
- return SecurityPlanImpl.forAllCertificates(hostnameVerificationEnabled, revocationCheckingStrategy);
- default:
- throw new ClientException("Unknown TLS authentication strategy: "
- + trustStrategy.strategy().name());
- }
- } else {
- return insecure();
- }
- }
-
public static class SecuritySettingsBuilder {
private boolean isCustomized = false;
private boolean encrypted;
diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingSettings.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingSettings.java
index 765d4686bd..b3767a08b7 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingSettings.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingSettings.java
@@ -22,7 +22,6 @@
public class RoutingSettings {
public static final long STALE_ROUTING_TABLE_PURGE_DELAY_MS = SECONDS.toMillis(30);
- public static final RoutingSettings DEFAULT = new RoutingSettings(STALE_ROUTING_TABLE_PURGE_DELAY_MS);
private final RoutingContext routingContext;
private final long routingTablePurgeDelayMs;
@@ -36,10 +35,6 @@ public RoutingSettings(long routingTablePurgeDelayMs, RoutingContext routingCont
this.routingTablePurgeDelayMs = routingTablePurgeDelayMs;
}
- public RoutingSettings withRoutingContext(RoutingContext newRoutingContext) {
- return new RoutingSettings(routingTablePurgeDelayMs, newRoutingContext);
- }
-
public RoutingContext routingContext() {
return routingContext;
}
diff --git a/driver/src/main/java/org/neo4j/driver/internal/retry/ExponentialBackoffRetryLogic.java b/driver/src/main/java/org/neo4j/driver/internal/retry/ExponentialBackoffRetryLogic.java
index 81b3f4cf33..f25bf8dac5 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/retry/ExponentialBackoffRetryLogic.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/retry/ExponentialBackoffRetryLogic.java
@@ -45,7 +45,7 @@
import reactor.util.retry.Retry;
public class ExponentialBackoffRetryLogic implements RetryLogic {
- static final long DEFAULT_MAX_RETRY_TIME_MS = SECONDS.toMillis(30);
+ public static final long DEFAULT_MAX_RETRY_TIME_MS = SECONDS.toMillis(30);
private static final long INITIAL_RETRY_DELAY_MS = SECONDS.toMillis(1);
private static final double RETRY_DELAY_MULTIPLIER = 2.0;
@@ -61,9 +61,9 @@ public class ExponentialBackoffRetryLogic implements RetryLogic {
private final Logger log;
public ExponentialBackoffRetryLogic(
- RetrySettings settings, EventExecutorGroup eventExecutorGroup, Clock clock, Logging logging) {
+ long maxTransactionRetryTime, EventExecutorGroup eventExecutorGroup, Clock clock, Logging logging) {
this(
- settings.maxRetryTimeMs(),
+ maxTransactionRetryTime,
INITIAL_RETRY_DELAY_MS,
RETRY_DELAY_MULTIPLIER,
RETRY_DELAY_JITTER_FACTOR,
diff --git a/driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlans.java b/driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlans.java
new file mode 100644
index 0000000000..c951a34efb
--- /dev/null
+++ b/driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlans.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) "Neo4j"
+ * Neo4j Sweden AB [http://neo4j.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.security;
+
+import static org.neo4j.driver.internal.Scheme.isHighTrustScheme;
+import static org.neo4j.driver.internal.Scheme.isSecurityScheme;
+import static org.neo4j.driver.internal.security.SecurityPlanImpl.insecure;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import org.neo4j.driver.Config;
+import org.neo4j.driver.RevocationCheckingStrategy;
+import org.neo4j.driver.exceptions.ClientException;
+import org.neo4j.driver.internal.Scheme;
+import org.neo4j.driver.internal.SecuritySettings;
+
+public class SecurityPlans {
+ public static SecurityPlan createSecurityPlan(SecuritySettings settings, String uriScheme) {
+ Scheme.validateScheme(uriScheme);
+ try {
+ if (isSecurityScheme(uriScheme)) {
+ assertSecuritySettingsNotUserConfigured(settings, uriScheme);
+ return createSecurityPlanFromScheme(uriScheme);
+ } else {
+ return createSecurityPlanImpl(settings.encrypted(), settings.trustStrategy());
+ }
+ } catch (GeneralSecurityException | IOException ex) {
+ throw new ClientException("Unable to establish SSL parameters", ex);
+ }
+ }
+
+ private static void assertSecuritySettingsNotUserConfigured(SecuritySettings settings, String uriScheme) {
+ if (isCustomized(settings)) {
+ throw new ClientException(String.format(
+ "Scheme %s is not configurable with manual encryption and trust settings", uriScheme));
+ }
+ }
+
+ public static boolean isCustomized(SecuritySettings securitySettings) {
+ return !(SecuritySettings.DEFAULT.encrypted() == securitySettings.encrypted()
+ && hasEqualTrustStrategy(securitySettings));
+ }
+
+ private static boolean hasEqualTrustStrategy(SecuritySettings settings) {
+ Config.TrustStrategy t1 = SecuritySettings.DEFAULT.trustStrategy();
+ Config.TrustStrategy t2 = settings.trustStrategy();
+ if (t1 == t2) {
+ return true;
+ }
+
+ return t1.isHostnameVerificationEnabled() == t2.isHostnameVerificationEnabled()
+ && t1.strategy() == t2.strategy()
+ && t1.certFiles().equals(t2.certFiles())
+ && t1.revocationCheckingStrategy() == t2.revocationCheckingStrategy();
+ }
+
+ private static SecurityPlan createSecurityPlanFromScheme(String scheme)
+ throws GeneralSecurityException, IOException {
+ if (isHighTrustScheme(scheme)) {
+ return SecurityPlanImpl.forSystemCASignedCertificates(true, RevocationCheckingStrategy.NO_CHECKS);
+ } else {
+ return SecurityPlanImpl.forAllCertificates(false, RevocationCheckingStrategy.NO_CHECKS);
+ }
+ }
+
+ /*
+ * Establish a complete SecurityPlan based on the details provided for
+ * driver construction.
+ */
+ private static SecurityPlan createSecurityPlanImpl(boolean encrypted, Config.TrustStrategy trustStrategy)
+ throws GeneralSecurityException, IOException {
+ if (encrypted) {
+ boolean hostnameVerificationEnabled = trustStrategy.isHostnameVerificationEnabled();
+ RevocationCheckingStrategy revocationCheckingStrategy = trustStrategy.revocationCheckingStrategy();
+ switch (trustStrategy.strategy()) {
+ case TRUST_CUSTOM_CA_SIGNED_CERTIFICATES:
+ return SecurityPlanImpl.forCustomCASignedCertificates(
+ trustStrategy.certFiles(), hostnameVerificationEnabled, revocationCheckingStrategy);
+ case TRUST_SYSTEM_CA_SIGNED_CERTIFICATES:
+ return SecurityPlanImpl.forSystemCASignedCertificates(
+ hostnameVerificationEnabled, revocationCheckingStrategy);
+ case TRUST_ALL_CERTIFICATES:
+ return SecurityPlanImpl.forAllCertificates(hostnameVerificationEnabled, revocationCheckingStrategy);
+ default:
+ throw new ClientException("Unknown TLS authentication strategy: "
+ + trustStrategy.strategy().name());
+ }
+ } else {
+ return insecure();
+ }
+ }
+}
diff --git a/driver/src/test/java/org/neo4j/driver/ConfigTest.java b/driver/src/test/java/org/neo4j/driver/ConfigTest.java
index 468e222ad8..e38515650c 100644
--- a/driver/src/test/java/org/neo4j/driver/ConfigTest.java
+++ b/driver/src/test/java/org/neo4j/driver/ConfigTest.java
@@ -21,7 +21,6 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -196,7 +195,7 @@ void shouldAllowZeroMaxRetryTimeMs() {
.withMaxTransactionRetryTime(0, TimeUnit.SECONDS)
.build();
- assertEquals(0, config.retrySettings().maxRetryTimeMs());
+ assertEquals(0, config.maxTransactionRetryTimeMillis());
}
@Test
@@ -205,7 +204,7 @@ void shouldAllowPositiveRetryAttempts() {
.withMaxTransactionRetryTime(42, TimeUnit.SECONDS)
.build();
- assertEquals(TimeUnit.SECONDS.toMillis(42), config.retrySettings().maxRetryTimeMs());
+ assertEquals(TimeUnit.SECONDS.toMillis(42), config.maxTransactionRetryTimeMillis());
}
@Test
@@ -384,6 +383,34 @@ void shouldSetMetricsAdapter() {
assertTrue(config.isMetricsEnabled());
}
+ @Test
+ void shouldSetRoutingTablePurgeDelayMillis() {
+ // GIVEN
+ var delay = 1000L;
+
+ // WHEN
+ var config = Config.builder()
+ .withRoutingTablePurgeDelay(delay, TimeUnit.MILLISECONDS)
+ .build();
+
+ // THEN
+ assertEquals(delay, config.routingTablePurgeDelayMillis());
+ }
+
+ @Test
+ void shouldMaxTransactionRetryTimeMillis() {
+ // GIVEN
+ var retryTime = 1000L;
+
+ // WHEN
+ var config = Config.builder()
+ .withMaxTransactionRetryTime(retryTime, TimeUnit.MILLISECONDS)
+ .build();
+
+ // THEN
+ assertEquals(retryTime, config.maxTransactionRetryTimeMillis());
+ }
+
@Nested
class SerializationTest {
@Test
@@ -413,11 +440,8 @@ void shouldSerialize() throws Exception {
assertEquals(config.connectionAcquisitionTimeoutMillis(), verify.connectionAcquisitionTimeoutMillis());
assertEquals(config.idleTimeBeforeConnectionTest(), verify.idleTimeBeforeConnectionTest());
assertEquals(config.maxConnectionLifetimeMillis(), verify.maxConnectionLifetimeMillis());
- assertNotNull(verify.retrySettings());
assertSame(DevNullLogging.DEV_NULL_LOGGING, verify.logging());
- assertEquals(
- config.retrySettings().maxRetryTimeMs(),
- verify.retrySettings().maxRetryTimeMs());
+ assertEquals(config.maxTransactionRetryTimeMillis(), verify.maxTransactionRetryTimeMillis());
assertEquals(config.fetchSize(), verify.fetchSize());
assertEquals(config.eventLoopThreads(), verify.eventLoopThreads());
assertEquals(config.encrypted(), verify.encrypted());
@@ -434,9 +458,7 @@ void shouldSerialize() throws Exception {
assertEquals(config.userAgent(), verify.userAgent());
assertEquals(config.isMetricsEnabled(), verify.isMetricsEnabled());
assertEquals(config.metricsAdapter(), verify.metricsAdapter());
- assertEquals(
- config.routingSettings().routingTablePurgeDelayMs(),
- verify.routingSettings().routingTablePurgeDelayMs());
+ assertEquals(config.maxTransactionRetryTimeMillis(), verify.maxTransactionRetryTimeMillis());
assertEquals(config.logLeakedSessions(), verify.logLeakedSessions());
}
diff --git a/driver/src/test/java/org/neo4j/driver/integration/ConnectionHandlingIT.java b/driver/src/test/java/org/neo4j/driver/integration/ConnectionHandlingIT.java
index cbbf4b9416..713e639002 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/ConnectionHandlingIT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/ConnectionHandlingIT.java
@@ -62,10 +62,8 @@
import org.neo4j.driver.internal.async.pool.ConnectionPoolImpl;
import org.neo4j.driver.internal.async.pool.PoolSettings;
import org.neo4j.driver.internal.cluster.RoutingContext;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.metrics.DevNullMetricsListener;
import org.neo4j.driver.internal.metrics.MetricsProvider;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlan;
import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.spi.Connection;
@@ -95,15 +93,8 @@ class ConnectionHandlingIT {
void createDriver() {
DriverFactoryWithConnectionPool driverFactory = new DriverFactoryWithConnectionPool();
AuthToken auth = neo4j.authToken();
- RoutingSettings routingSettings = RoutingSettings.DEFAULT;
- RetrySettings retrySettings = RetrySettings.DEFAULT;
driver = driverFactory.newInstance(
- neo4j.uri(),
- auth,
- routingSettings,
- retrySettings,
- Config.builder().withFetchSize(1).build(),
- SecurityPlanImpl.insecure());
+ neo4j.uri(), auth, Config.builder().withFetchSize(1).build(), SecurityPlanImpl.insecure(), null, null);
connectionPool = driverFactory.connectionPool;
connectionPool.startMemorizing(); // start memorizing connections after driver creation
}
diff --git a/driver/src/test/java/org/neo4j/driver/integration/ConnectionPoolIT.java b/driver/src/test/java/org/neo4j/driver/integration/ConnectionPoolIT.java
index a9295243f3..29a3130a18 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/ConnectionPoolIT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/ConnectionPoolIT.java
@@ -26,7 +26,6 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
-import static org.neo4j.driver.internal.retry.RetrySettings.DEFAULT;
import static org.neo4j.driver.internal.util.Matchers.connectionAcquisitionTimeoutError;
import io.netty.channel.Channel;
@@ -44,7 +43,6 @@
import org.neo4j.driver.Session;
import org.neo4j.driver.Transaction;
import org.neo4j.driver.exceptions.ClientException;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.util.FakeClock;
import org.neo4j.driver.internal.util.io.ChannelTrackingDriverFactory;
@@ -97,7 +95,7 @@ void shouldDisposeChannelsBasedOnMaxLifetime() throws Exception {
.withMaxConnectionLifetime(maxConnLifetimeHours, TimeUnit.HOURS)
.build();
driver = driverFactory.newInstance(
- neo4j.uri(), neo4j.authToken(), RoutingSettings.DEFAULT, DEFAULT, config, SecurityPlanImpl.insecure());
+ neo4j.uri(), neo4j.authToken(), config, SecurityPlanImpl.insecure(), null, null);
// force driver create channel and return it to the pool
startAndCloseTransactions(driver, 1);
diff --git a/driver/src/test/java/org/neo4j/driver/integration/ErrorIT.java b/driver/src/test/java/org/neo4j/driver/integration/ErrorIT.java
index 33edafd4a0..95c24f2778 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/ErrorIT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/ErrorIT.java
@@ -57,9 +57,7 @@
import org.neo4j.driver.Transaction;
import org.neo4j.driver.exceptions.ClientException;
import org.neo4j.driver.exceptions.ServiceUnavailableException;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.messaging.response.FailureMessage;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.util.FailingMessageFormat;
import org.neo4j.driver.internal.util.FakeClock;
@@ -261,13 +259,11 @@ private Throwable testChannelErrorHandling(Consumer messag
URI uri = session.uri();
AuthToken authToken = session.authToken();
- RoutingSettings routingSettings = RoutingSettings.DEFAULT;
- RetrySettings retrySettings = RetrySettings.DEFAULT;
Config config = Config.builder().withLogging(DEV_NULL_LOGGING).build();
Throwable queryError = null;
- try (Driver driver = driverFactory.newInstance(
- uri, authToken, routingSettings, retrySettings, config, SecurityPlanImpl.insecure())) {
+ try (Driver driver =
+ driverFactory.newInstance(uri, authToken, config, SecurityPlanImpl.insecure(), null, null)) {
driver.verifyConnectivity();
try (Session session = driver.session()) {
messageFormatSetup.accept(driverFactory.getFailingMessageFormat());
diff --git a/driver/src/test/java/org/neo4j/driver/integration/ServerKilledIT.java b/driver/src/test/java/org/neo4j/driver/integration/ServerKilledIT.java
index a2b1739adf..7f847f104a 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/ServerKilledIT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/ServerKilledIT.java
@@ -36,8 +36,6 @@
import org.neo4j.driver.Session;
import org.neo4j.driver.exceptions.ServiceUnavailableException;
import org.neo4j.driver.internal.DriverFactory;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.util.Clock;
import org.neo4j.driver.internal.util.DriverFactoryWithClock;
@@ -129,9 +127,6 @@ private static void acquireAndReleaseConnections(int count, Driver driver) {
private Driver createDriver(Clock clock, Config config) {
DriverFactory factory = new DriverFactoryWithClock(clock);
- RoutingSettings routingSettings = RoutingSettings.DEFAULT;
- RetrySettings retrySettings = RetrySettings.DEFAULT;
- return factory.newInstance(
- neo4j.uri(), neo4j.authToken(), routingSettings, retrySettings, config, SecurityPlanImpl.insecure());
+ return factory.newInstance(neo4j.uri(), neo4j.authToken(), config, SecurityPlanImpl.insecure(), null, null);
}
}
diff --git a/driver/src/test/java/org/neo4j/driver/integration/SessionBoltV3IT.java b/driver/src/test/java/org/neo4j/driver/integration/SessionBoltV3IT.java
index fd83bf1e2e..143d148028 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/SessionBoltV3IT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/SessionBoltV3IT.java
@@ -56,11 +56,9 @@
import org.neo4j.driver.async.ResultCursor;
import org.neo4j.driver.exceptions.ClientException;
import org.neo4j.driver.exceptions.TransientException;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.messaging.Message;
import org.neo4j.driver.internal.messaging.request.GoodbyeMessage;
import org.neo4j.driver.internal.messaging.request.HelloMessage;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.util.EnabledOnNeo4jWith;
import org.neo4j.driver.internal.util.MessageRecordingDriverFactory;
@@ -275,12 +273,7 @@ void shouldSendGoodbyeWhenClosingDriver() {
MessageRecordingDriverFactory driverFactory = new MessageRecordingDriverFactory();
try (Driver otherDriver = driverFactory.newInstance(
- driver.uri(),
- driver.authToken(),
- RoutingSettings.DEFAULT,
- RetrySettings.DEFAULT,
- defaultConfig(),
- SecurityPlanImpl.insecure())) {
+ driver.uri(), driver.authToken(), defaultConfig(), SecurityPlanImpl.insecure(), null, null)) {
List sessions = new ArrayList<>();
List txs = new ArrayList<>();
for (int i = 0; i < txCount; i++) {
diff --git a/driver/src/test/java/org/neo4j/driver/integration/SessionIT.java b/driver/src/test/java/org/neo4j/driver/integration/SessionIT.java
index 9bd03b8ab2..4655f8fe66 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/SessionIT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/SessionIT.java
@@ -83,8 +83,6 @@
import org.neo4j.driver.exceptions.ServiceUnavailableException;
import org.neo4j.driver.exceptions.TransientException;
import org.neo4j.driver.internal.DriverFactory;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.util.DisabledOnNeo4jWith;
import org.neo4j.driver.internal.util.DriverFactoryWithFixedRetryLogic;
@@ -1275,12 +1273,7 @@ private Driver newDriverWithoutRetries() {
private Driver newDriverWithFixedRetries(int maxRetriesCount) {
DriverFactory driverFactory = new DriverFactoryWithFixedRetryLogic(maxRetriesCount);
return driverFactory.newInstance(
- neo4j.uri(),
- neo4j.authToken(),
- RoutingSettings.DEFAULT,
- RetrySettings.DEFAULT,
- noLoggingConfig(),
- SecurityPlanImpl.insecure());
+ neo4j.uri(), neo4j.authToken(), noLoggingConfig(), SecurityPlanImpl.insecure(), null, null);
}
private Driver newDriverWithLimitedRetries(int maxTxRetryTime, TimeUnit unit) {
diff --git a/driver/src/test/java/org/neo4j/driver/integration/SharedEventLoopIT.java b/driver/src/test/java/org/neo4j/driver/integration/SharedEventLoopIT.java
index 6195d56bc2..ca2348533e 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/SharedEventLoopIT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/SharedEventLoopIT.java
@@ -29,8 +29,6 @@
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.internal.DriverFactory;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.testutil.DatabaseExtension;
import org.neo4j.driver.testutil.ParallelizableIT;
@@ -85,11 +83,9 @@ private Driver createDriver(EventLoopGroup eventLoopGroup) {
return driverFactory.newInstance(
neo4j.uri(),
neo4j.authToken(),
- RoutingSettings.DEFAULT,
- RetrySettings.DEFAULT,
Config.defaultConfig(),
- eventLoopGroup,
SecurityPlanImpl.insecure(),
+ eventLoopGroup,
null);
}
diff --git a/driver/src/test/java/org/neo4j/driver/integration/TransactionIT.java b/driver/src/test/java/org/neo4j/driver/integration/TransactionIT.java
index bc95380e02..c043e08901 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/TransactionIT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/TransactionIT.java
@@ -28,7 +28,6 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING;
-import static org.neo4j.driver.internal.retry.RetrySettings.DEFAULT;
import static org.neo4j.driver.testutil.TestUtil.assertNoCircularReferences;
import io.netty.channel.Channel;
@@ -46,7 +45,6 @@
import org.neo4j.driver.Value;
import org.neo4j.driver.exceptions.ClientException;
import org.neo4j.driver.exceptions.ServiceUnavailableException;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.util.Clock;
import org.neo4j.driver.internal.util.io.ChannelTrackingDriverFactory;
@@ -352,12 +350,7 @@ void shouldThrowWhenConnectionKilledDuringTransaction() {
Config config = Config.builder().withLogging(DEV_NULL_LOGGING).build();
try (Driver driver = factory.newInstance(
- session.uri(),
- session.authToken(),
- RoutingSettings.DEFAULT,
- DEFAULT,
- config,
- SecurityPlanImpl.insecure())) {
+ session.uri(), session.authToken(), config, SecurityPlanImpl.insecure(), null, null)) {
ServiceUnavailableException e = assertThrows(ServiceUnavailableException.class, () -> {
try (Session session1 = driver.session();
Transaction tx = session1.beginTransaction()) {
diff --git a/driver/src/test/java/org/neo4j/driver/integration/UnmanagedTransactionIT.java b/driver/src/test/java/org/neo4j/driver/integration/UnmanagedTransactionIT.java
index d6a0df7f51..455794df31 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/UnmanagedTransactionIT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/UnmanagedTransactionIT.java
@@ -49,8 +49,6 @@
import org.neo4j.driver.internal.InternalDriver;
import org.neo4j.driver.internal.async.NetworkSession;
import org.neo4j.driver.internal.async.UnmanagedTransaction;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.util.Clock;
import org.neo4j.driver.internal.util.io.ChannelTrackingDriverFactory;
@@ -201,12 +199,7 @@ private void testCommitAndRollbackFailurePropagation(boolean commit) {
Config config = Config.builder().withLogging(DEV_NULL_LOGGING).build();
try (Driver driver = driverFactory.newInstance(
- neo4j.uri(),
- neo4j.authToken(),
- RoutingSettings.DEFAULT,
- RetrySettings.DEFAULT,
- config,
- SecurityPlanImpl.insecure())) {
+ neo4j.uri(), neo4j.authToken(), config, SecurityPlanImpl.insecure(), null, null)) {
NetworkSession session = ((InternalDriver) driver).newSession(SessionConfig.defaultConfig());
{
UnmanagedTransaction tx = beginTransaction(session);
diff --git a/driver/src/test/java/org/neo4j/driver/internal/CustomSecurityPlanTest.java b/driver/src/test/java/org/neo4j/driver/internal/CustomSecurityPlanTest.java
index c45ef9b7ea..cf2cb78b71 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/CustomSecurityPlanTest.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/CustomSecurityPlanTest.java
@@ -31,9 +31,7 @@
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Config;
import org.neo4j.driver.internal.cluster.RoutingContext;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.metrics.MetricsProvider;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlan;
import org.neo4j.driver.internal.spi.ConnectionPool;
@@ -47,11 +45,9 @@ void testCustomSecurityPlanUsed() {
driverFactory.newInstance(
URI.create("neo4j://somewhere:1234"),
AuthTokens.none(),
- RoutingSettings.DEFAULT,
- RetrySettings.DEFAULT,
Config.defaultConfig(),
- null,
securityPlan,
+ null,
null);
assertFalse(driverFactory.capturedSecurityPlans.isEmpty());
diff --git a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java
index 6c993deda1..95205ce939 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java
@@ -70,9 +70,7 @@
import org.neo4j.driver.internal.metrics.MetricsProvider;
import org.neo4j.driver.internal.metrics.MicrometerMetricsProvider;
import org.neo4j.driver.internal.retry.RetryLogic;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlan;
-import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.spi.Connection;
import org.neo4j.driver.internal.spi.ConnectionPool;
import org.neo4j.driver.internal.spi.ConnectionProvider;
@@ -202,19 +200,10 @@ void shouldCreateAppropriateDriverType(String uri) {
void shouldUseBuiltInRediscoveryByDefault() {
// GIVEN
var driverFactory = new DriverFactory();
- var securityPlan =
- new SecuritySettings.SecuritySettingsBuilder().build().createSecurityPlan("neo4j");
// WHEN
var driver = driverFactory.newInstance(
- URI.create("neo4j://localhost:7687"),
- AuthTokens.none(),
- RoutingSettings.DEFAULT,
- RetrySettings.DEFAULT,
- Config.defaultConfig(),
- null,
- securityPlan,
- null);
+ URI.create("neo4j://localhost:7687"), AuthTokens.none(), Config.defaultConfig(), null, null, null);
// THEN
var sessionFactory = ((InternalDriver) driver).getSessionFactory();
@@ -227,8 +216,6 @@ void shouldUseBuiltInRediscoveryByDefault() {
void shouldUseSuppliedRediscovery() {
// GIVEN
var driverFactory = new DriverFactory();
- var securityPlan =
- new SecuritySettings.SecuritySettingsBuilder().build().createSecurityPlan("neo4j");
@SuppressWarnings("unchecked")
Supplier rediscoverySupplier = mock(Supplier.class);
var rediscovery = mock(Rediscovery.class);
@@ -238,11 +225,9 @@ void shouldUseSuppliedRediscovery() {
var driver = driverFactory.newInstance(
URI.create("neo4j://localhost:7687"),
AuthTokens.none(),
- RoutingSettings.DEFAULT,
- RetrySettings.DEFAULT,
Config.defaultConfig(),
null,
- securityPlan,
+ null,
rediscoverySupplier);
// THEN
@@ -259,13 +244,7 @@ private Driver createDriver(String uri, DriverFactory driverFactory) {
private Driver createDriver(String uri, DriverFactory driverFactory, Config config) {
AuthToken auth = AuthTokens.none();
- return driverFactory.newInstance(
- URI.create(uri),
- auth,
- RoutingSettings.DEFAULT,
- RetrySettings.DEFAULT,
- config,
- SecurityPlanImpl.insecure());
+ return driverFactory.newInstance(URI.create(uri), auth, config);
}
private static ConnectionPool connectionPoolMock() {
diff --git a/driver/src/test/java/org/neo4j/driver/internal/SecuritySettingsTest.java b/driver/src/test/java/org/neo4j/driver/internal/SecuritySettingsTest.java
index 86c0688f5e..0548842410 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/SecuritySettingsTest.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/SecuritySettingsTest.java
@@ -20,208 +20,19 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.neo4j.driver.RevocationCheckingStrategy.NO_CHECKS;
-import static org.neo4j.driver.RevocationCheckingStrategy.STRICT;
-import static org.neo4j.driver.RevocationCheckingStrategy.VERIFY_IF_PRESENT;
+import static org.neo4j.driver.internal.security.SecurityPlans.isCustomized;
import java.io.File;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.stream.Stream;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.MethodSource;
-import org.junit.platform.commons.support.ReflectionSupport;
import org.neo4j.driver.Config;
-import org.neo4j.driver.exceptions.ClientException;
-import org.neo4j.driver.internal.security.SecurityPlan;
import org.neo4j.driver.testutil.TestUtil;
class SecuritySettingsTest {
- private static Stream selfSignedSchemes() {
- return Stream.of("bolt+ssc", "neo4j+ssc");
- }
-
- private static Stream systemCertSchemes() {
- return Stream.of("neo4j+s", "bolt+s");
- }
-
- private static Stream unencryptedSchemes() {
- return Stream.of("neo4j", "bolt");
- }
-
- private static Stream allSecureSchemes() {
- return Stream.concat(selfSignedSchemes(), systemCertSchemes());
- }
-
- @ParameterizedTest
- @MethodSource("allSecureSchemes")
- void testEncryptionSchemeEnablesEncryption(String scheme) {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder().build();
-
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(scheme);
-
- assertTrue(securityPlan.requiresEncryption());
- }
-
- @ParameterizedTest
- @MethodSource("systemCertSchemes")
- void testSystemCertCompatibleConfiguration(String scheme) throws Exception {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder().build();
-
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(scheme);
-
- assertTrue(securityPlan.requiresEncryption());
- assertTrue(securityPlan.requiresHostnameVerification());
- assertEquals(NO_CHECKS, securityPlan.revocationCheckingStrategy());
- }
-
- @ParameterizedTest
- @MethodSource("selfSignedSchemes")
- void testSelfSignedCertConfigDisablesHostnameVerification(String scheme) throws Exception {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder().build();
-
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(scheme);
-
- assertTrue(securityPlan.requiresEncryption());
- assertFalse(securityPlan.requiresHostnameVerification());
- }
-
- @ParameterizedTest
- @MethodSource("allSecureSchemes")
- void testThrowsOnUserCustomizedEncryption(String scheme) {
- SecuritySettings securitySettings =
- new SecuritySettings.SecuritySettingsBuilder().withEncryption().build();
-
- ClientException ex = assertThrows(ClientException.class, () -> securitySettings.createSecurityPlan(scheme));
-
- assertTrue(ex.getMessage()
- .contains(String.format(
- "Scheme %s is not configurable with manual encryption and trust settings", scheme)));
- }
-
- @ParameterizedTest
- @MethodSource("allSecureSchemes")
- void testThrowsOnUserCustomizedTrustConfiguration(String scheme) {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
- .withTrustStrategy(Config.TrustStrategy.trustAllCertificates())
- .build();
-
- ClientException ex = assertThrows(ClientException.class, () -> securitySettings.createSecurityPlan(scheme));
-
- assertTrue(ex.getMessage()
- .contains(String.format(
- "Scheme %s is not configurable with manual encryption and trust settings", scheme)));
- }
-
- @ParameterizedTest
- @MethodSource("allSecureSchemes")
- void testThrowsOnUserCustomizedTrustConfigurationAndEncryption(String scheme) {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
- .withTrustStrategy(Config.TrustStrategy.trustSystemCertificates())
- .withEncryption()
- .build();
-
- ClientException ex = assertThrows(ClientException.class, () -> securitySettings.createSecurityPlan(scheme));
-
- assertTrue(ex.getMessage()
- .contains(String.format(
- "Scheme %s is not configurable with manual encryption and trust settings", scheme)));
- }
-
- @ParameterizedTest
- @MethodSource("unencryptedSchemes")
- void testNoEncryption(String scheme) {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder().build();
-
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(scheme);
-
- assertFalse(securityPlan.requiresEncryption());
- }
-
- @ParameterizedTest
- @MethodSource("unencryptedSchemes")
- void testConfiguredEncryption(String scheme) {
- SecuritySettings securitySettings =
- new SecuritySettings.SecuritySettingsBuilder().withEncryption().build();
-
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(scheme);
-
- assertTrue(securityPlan.requiresEncryption());
- }
-
- @ParameterizedTest
- @MethodSource("unencryptedSchemes")
- void testConfiguredAllCertificates(String scheme) {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
- .withEncryption()
- .withTrustStrategy(Config.TrustStrategy.trustAllCertificates())
- .build();
-
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(scheme);
-
- assertTrue(securityPlan.requiresEncryption());
- }
-
- @ParameterizedTest
- @MethodSource("unencryptedSchemes")
- void testConfigureStrictRevocationChecking(String scheme) {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
- .withTrustStrategy(
- Config.TrustStrategy.trustSystemCertificates().withStrictRevocationChecks())
- .withEncryption()
- .build();
-
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(scheme);
-
- assertEquals(STRICT, securityPlan.revocationCheckingStrategy());
- }
-
- @ParameterizedTest
- @MethodSource("unencryptedSchemes")
- void testConfigureVerifyIfPresentRevocationChecking(String scheme) {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
- .withTrustStrategy(
- Config.TrustStrategy.trustSystemCertificates().withVerifyIfPresentRevocationChecks())
- .withEncryption()
- .build();
-
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(scheme);
-
- assertEquals(VERIFY_IF_PRESENT, securityPlan.revocationCheckingStrategy());
- }
-
- @ParameterizedTest
- @MethodSource("unencryptedSchemes")
- void testRevocationCheckingDisabledByDefault(String scheme) {
- SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
- .withTrustStrategy(Config.TrustStrategy.trustSystemCertificates())
- .withEncryption()
- .build();
-
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(scheme);
-
- assertEquals(NO_CHECKS, securityPlan.revocationCheckingStrategy());
- }
-
@Nested
class SerializationTests {
- Method isCustomized = ReflectionSupport.findMethod(SecuritySettings.class, "isCustomized")
- .orElseThrow(() -> new RuntimeException("This test requires isCustomized to be present."));
-
- boolean isCustomized(SecuritySettings securitySettings) {
- isCustomized.setAccessible(true);
- try {
- return (boolean) isCustomized.invoke(securitySettings);
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
-
@Test
void defaultSettingsShouldNotBeCustomizedWhenReadBack() throws IOException, ClassNotFoundException {
SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder().build();
diff --git a/driver/src/test/java/org/neo4j/driver/internal/retry/ExponentialBackoffRetryLogicTest.java b/driver/src/test/java/org/neo4j/driver/internal/retry/ExponentialBackoffRetryLogicTest.java
index c1ef18454e..becfec09f1 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/retry/ExponentialBackoffRetryLogicTest.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/retry/ExponentialBackoffRetryLogicTest.java
@@ -751,7 +751,7 @@ void doesRetryOnClientExceptionWithRetryableCause() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
String result = logic.retry(() -> {
@@ -771,7 +771,7 @@ void doesRetryOnAuthorizationExpiredException() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
String result = logic.retry(() -> {
@@ -791,7 +791,7 @@ void doesRetryOnConnectionReadTimeoutException() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
String result = logic.retry(() -> {
@@ -811,7 +811,7 @@ void doesNotRetryOnRandomClientException() {
Logger logger = mock(Logger.class);
when(logging.getLog(anyString())).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
ClientException exception = Assertions.assertThrows(
@@ -834,7 +834,7 @@ void eachRetryIsLogged() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
retry(logic, retries);
@@ -850,7 +850,7 @@ void doesRetryOnClientExceptionWithRetryableCauseAsync() {
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
String result = await(logic.retryAsync(() -> {
@@ -870,7 +870,7 @@ void doesRetryOnAuthorizationExpiredExceptionAsync() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
String result = await(logic.retryAsync(() -> {
@@ -891,7 +891,7 @@ void doesNotRetryOnRandomClientExceptionAsync() {
when(logging.getLog(anyString())).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
ClientException exception = Assertions.assertThrows(
@@ -916,7 +916,7 @@ void eachRetryIsLoggedAsync() {
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
assertEquals(result, await(retryAsync(logic, retries, result)));
@@ -934,7 +934,7 @@ void doesRetryOnClientExceptionWithRetryableCauseRx() {
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
String result = await(Mono.from(logic.retryRx(Mono.fromSupplier(() -> {
@@ -954,7 +954,7 @@ void doesRetryOnAuthorizationExpiredExceptionRx() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
String result = await(Mono.from(logic.retryRx(Mono.fromSupplier(() -> {
@@ -974,7 +974,7 @@ void doesRetryOnAsyncResourceCleanupRuntimeExceptionRx() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
String result = await(Mono.from(logic.retryRx(Mono.fromSupplier(() -> {
@@ -995,7 +995,7 @@ void doesNotRetryOnRandomClientExceptionRx() {
when(logging.getLog(anyString())).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
ClientException exception = Assertions.assertThrows(
@@ -1020,7 +1020,7 @@ void eachRetryIsLoggedRx() {
when(logging.getLog(any(Class.class))).thenReturn(logger);
ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, clock, logging);
+ new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, clock, logging);
assertEquals(result, await(Flux.from(retryRx(logic, retries, result)).single()));
@@ -1035,8 +1035,8 @@ void nothingIsLoggedOnFatalFailure() {
Logging logging = mock(Logging.class);
Logger logger = mock(Logger.class);
when(logging.getLog(anyString())).thenReturn(logger);
- ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, mock(Clock.class), logging);
+ ExponentialBackoffRetryLogic logic = new ExponentialBackoffRetryLogic(
+ RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, mock(Clock.class), logging);
RuntimeException error = assertThrows(
RuntimeException.class,
@@ -1052,8 +1052,8 @@ void nothingIsLoggedOnFatalFailureAsync() {
Logging logging = mock(Logging.class);
Logger logger = mock(Logger.class);
when(logging.getLog(anyString())).thenReturn(logger);
- ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, mock(Clock.class), logging);
+ ExponentialBackoffRetryLogic logic = new ExponentialBackoffRetryLogic(
+ RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, mock(Clock.class), logging);
RuntimeException error = assertThrows(
RuntimeException.class,
@@ -1068,8 +1068,8 @@ void nothingIsLoggedOnFatalFailureRx() {
Logging logging = mock(Logging.class);
Logger logger = mock(Logger.class);
when(logging.getLog(anyString())).thenReturn(logger);
- ExponentialBackoffRetryLogic logic =
- new ExponentialBackoffRetryLogic(RetrySettings.DEFAULT, eventExecutor, mock(Clock.class), logging);
+ ExponentialBackoffRetryLogic logic = new ExponentialBackoffRetryLogic(
+ RetrySettings.DEFAULT.maxRetryTimeMs(), eventExecutor, mock(Clock.class), logging);
Publisher retryRx = logic.retryRx(Mono.error(new RuntimeException("Fatal rx")));
RuntimeException error = assertThrows(RuntimeException.class, () -> await(retryRx));
@@ -1085,7 +1085,7 @@ void correctNumberOfRetiesAreLoggedOnFailure() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
RetrySettings settings = RetrySettings.DEFAULT;
- RetryLogic logic = new ExponentialBackoffRetryLogic(settings, eventExecutor, clock, logging);
+ RetryLogic logic = new ExponentialBackoffRetryLogic(settings.maxRetryTimeMs(), eventExecutor, clock, logging);
ServiceUnavailableException error = assertThrows(
ServiceUnavailableException.class,
@@ -1116,7 +1116,7 @@ void correctNumberOfRetiesAreLoggedOnFailureAsync() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
RetrySettings settings = RetrySettings.DEFAULT;
- RetryLogic logic = new ExponentialBackoffRetryLogic(settings, eventExecutor, clock, logging);
+ RetryLogic logic = new ExponentialBackoffRetryLogic(settings.maxRetryTimeMs(), eventExecutor, clock, logging);
SessionExpiredException error = assertThrows(
SessionExpiredException.class,
@@ -1149,7 +1149,7 @@ void correctNumberOfRetiesAreLoggedOnFailureRx() {
Logger logger = mock(Logger.class);
when(logging.getLog(any(Class.class))).thenReturn(logger);
RetrySettings settings = RetrySettings.DEFAULT;
- RetryLogic logic = new ExponentialBackoffRetryLogic(settings, eventExecutor, clock, logging);
+ RetryLogic logic = new ExponentialBackoffRetryLogic(settings.maxRetryTimeMs(), eventExecutor, clock, logging);
AtomicBoolean invoked = new AtomicBoolean(false);
SessionExpiredException error = assertThrows(
diff --git a/driver/src/test/java/org/neo4j/driver/internal/security/SecurityPlans.java b/driver/src/test/java/org/neo4j/driver/internal/security/SecurityPlans.java
new file mode 100644
index 0000000000..5419c18f34
--- /dev/null
+++ b/driver/src/test/java/org/neo4j/driver/internal/security/SecurityPlans.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) "Neo4j"
+ * Neo4j Sweden AB [http://neo4j.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.security;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.neo4j.driver.RevocationCheckingStrategy.NO_CHECKS;
+import static org.neo4j.driver.RevocationCheckingStrategy.STRICT;
+import static org.neo4j.driver.RevocationCheckingStrategy.VERIFY_IF_PRESENT;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.neo4j.driver.Config;
+import org.neo4j.driver.exceptions.ClientException;
+import org.neo4j.driver.internal.SecuritySettings;
+
+class SecurityPlansTest {
+ private static Stream selfSignedSchemes() {
+ return Stream.of("bolt+ssc", "neo4j+ssc");
+ }
+
+ private static Stream systemCertSchemes() {
+ return Stream.of("neo4j+s", "bolt+s");
+ }
+
+ private static Stream unencryptedSchemes() {
+ return Stream.of("neo4j", "bolt");
+ }
+
+ private static Stream allSecureSchemes() {
+ return Stream.concat(selfSignedSchemes(), systemCertSchemes());
+ }
+
+ @ParameterizedTest
+ @MethodSource("allSecureSchemes")
+ void testEncryptionSchemeEnablesEncryption(String scheme) {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder().build();
+
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme);
+
+ assertTrue(securityPlan.requiresEncryption());
+ }
+
+ @ParameterizedTest
+ @MethodSource("systemCertSchemes")
+ void testSystemCertCompatibleConfiguration(String scheme) throws Exception {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder().build();
+
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme);
+
+ assertTrue(securityPlan.requiresEncryption());
+ assertTrue(securityPlan.requiresHostnameVerification());
+ assertEquals(NO_CHECKS, securityPlan.revocationCheckingStrategy());
+ }
+
+ @ParameterizedTest
+ @MethodSource("selfSignedSchemes")
+ void testSelfSignedCertConfigDisablesHostnameVerification(String scheme) throws Exception {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder().build();
+
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme);
+
+ assertTrue(securityPlan.requiresEncryption());
+ assertFalse(securityPlan.requiresHostnameVerification());
+ }
+
+ @ParameterizedTest
+ @MethodSource("allSecureSchemes")
+ void testThrowsOnUserCustomizedEncryption(String scheme) {
+ SecuritySettings securitySettings =
+ new SecuritySettings.SecuritySettingsBuilder().withEncryption().build();
+
+ ClientException ex =
+ assertThrows(ClientException.class, () -> SecurityPlans.createSecurityPlan(securitySettings, scheme));
+
+ assertTrue(ex.getMessage()
+ .contains(String.format(
+ "Scheme %s is not configurable with manual encryption and trust settings", scheme)));
+ }
+
+ @ParameterizedTest
+ @MethodSource("allSecureSchemes")
+ void testThrowsOnUserCustomizedTrustConfiguration(String scheme) {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
+ .withTrustStrategy(Config.TrustStrategy.trustAllCertificates())
+ .build();
+
+ ClientException ex =
+ assertThrows(ClientException.class, () -> SecurityPlans.createSecurityPlan(securitySettings, scheme));
+
+ assertTrue(ex.getMessage()
+ .contains(String.format(
+ "Scheme %s is not configurable with manual encryption and trust settings", scheme)));
+ }
+
+ @ParameterizedTest
+ @MethodSource("allSecureSchemes")
+ void testThrowsOnUserCustomizedTrustConfigurationAndEncryption(String scheme) {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
+ .withTrustStrategy(Config.TrustStrategy.trustSystemCertificates())
+ .withEncryption()
+ .build();
+
+ ClientException ex =
+ assertThrows(ClientException.class, () -> SecurityPlans.createSecurityPlan(securitySettings, scheme));
+
+ assertTrue(ex.getMessage()
+ .contains(String.format(
+ "Scheme %s is not configurable with manual encryption and trust settings", scheme)));
+ }
+
+ @ParameterizedTest
+ @MethodSource("unencryptedSchemes")
+ void testNoEncryption(String scheme) {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder().build();
+
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme);
+
+ assertFalse(securityPlan.requiresEncryption());
+ }
+
+ @ParameterizedTest
+ @MethodSource("unencryptedSchemes")
+ void testConfiguredEncryption(String scheme) {
+ SecuritySettings securitySettings =
+ new SecuritySettings.SecuritySettingsBuilder().withEncryption().build();
+
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme);
+
+ assertTrue(securityPlan.requiresEncryption());
+ }
+
+ @ParameterizedTest
+ @MethodSource("unencryptedSchemes")
+ void testConfiguredAllCertificates(String scheme) {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
+ .withEncryption()
+ .withTrustStrategy(Config.TrustStrategy.trustAllCertificates())
+ .build();
+
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme);
+
+ assertTrue(securityPlan.requiresEncryption());
+ }
+
+ @ParameterizedTest
+ @MethodSource("unencryptedSchemes")
+ void testConfigureStrictRevocationChecking(String scheme) {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
+ .withTrustStrategy(
+ Config.TrustStrategy.trustSystemCertificates().withStrictRevocationChecks())
+ .withEncryption()
+ .build();
+
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme);
+
+ assertEquals(STRICT, securityPlan.revocationCheckingStrategy());
+ }
+
+ @ParameterizedTest
+ @MethodSource("unencryptedSchemes")
+ void testConfigureVerifyIfPresentRevocationChecking(String scheme) {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
+ .withTrustStrategy(
+ Config.TrustStrategy.trustSystemCertificates().withVerifyIfPresentRevocationChecks())
+ .withEncryption()
+ .build();
+
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme);
+
+ assertEquals(VERIFY_IF_PRESENT, securityPlan.revocationCheckingStrategy());
+ }
+
+ @ParameterizedTest
+ @MethodSource("unencryptedSchemes")
+ void testRevocationCheckingDisabledByDefault(String scheme) {
+ SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder()
+ .withTrustStrategy(Config.TrustStrategy.trustSystemCertificates())
+ .withEncryption()
+ .build();
+
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme);
+
+ assertEquals(NO_CHECKS, securityPlan.revocationCheckingStrategy());
+ }
+}
diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/DriverFactoryWithFixedRetryLogic.java b/driver/src/test/java/org/neo4j/driver/internal/util/DriverFactoryWithFixedRetryLogic.java
index dec57cbafd..2a668b4729 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/util/DriverFactoryWithFixedRetryLogic.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/util/DriverFactoryWithFixedRetryLogic.java
@@ -22,7 +22,6 @@
import org.neo4j.driver.Logging;
import org.neo4j.driver.internal.DriverFactory;
import org.neo4j.driver.internal.retry.RetryLogic;
-import org.neo4j.driver.internal.retry.RetrySettings;
public class DriverFactoryWithFixedRetryLogic extends DriverFactory {
private final int retryCount;
@@ -33,7 +32,7 @@ public DriverFactoryWithFixedRetryLogic(int retryCount) {
@Override
protected RetryLogic createRetryLogic(
- RetrySettings settings, EventExecutorGroup eventExecutorGroup, Logging logging) {
+ long maxTransactionRetryTime, EventExecutorGroup eventExecutorGroup, Logging logging) {
return new FixedRetryLogic(retryCount);
}
}
diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/FixedRetryLogic.java b/driver/src/test/java/org/neo4j/driver/internal/util/FixedRetryLogic.java
index 13dcd22584..f3c6e6707a 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/util/FixedRetryLogic.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/util/FixedRetryLogic.java
@@ -22,7 +22,6 @@
import io.netty.util.concurrent.EventExecutorGroup;
import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic;
-import org.neo4j.driver.internal.retry.RetrySettings;
public class FixedRetryLogic extends ExponentialBackoffRetryLogic {
private final int retryCount;
@@ -33,7 +32,7 @@ public FixedRetryLogic(int retryCount) {
}
public FixedRetryLogic(int retryCount, EventExecutorGroup eventExecutorGroup) {
- super(new RetrySettings(Long.MAX_VALUE), eventExecutorGroup, new SleeplessClock(), DEV_NULL_LOGGING);
+ super(Long.MAX_VALUE, eventExecutorGroup, new SleeplessClock(), DEV_NULL_LOGGING);
this.retryCount = retryCount;
}
diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java
index 62217f4f1c..09f02a68fd 100644
--- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java
+++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java
@@ -50,10 +50,9 @@
import org.neo4j.driver.internal.DomainNameResolver;
import org.neo4j.driver.internal.DriverFactory;
import org.neo4j.driver.internal.SecuritySettings;
-import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.cluster.loadbalancing.LoadBalancer;
-import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlan;
+import org.neo4j.driver.internal.security.SecurityPlans;
import org.neo4j.driver.net.ServerAddressResolver;
import reactor.core.publisher.Mono;
@@ -104,9 +103,9 @@ public TestkitResponse process(TestkitState testkitState) {
Optional.ofNullable(data.connectionTimeoutMs)
.ifPresent(timeout -> configBuilder.withConnectionTimeout(timeout, TimeUnit.MILLISECONDS));
Optional.ofNullable(data.fetchSize).ifPresent(configBuilder::withFetchSize);
- RetrySettings retrySettings = Optional.ofNullable(data.maxTxRetryTimeMs)
- .map(RetrySettings::new)
- .orElse(RetrySettings.DEFAULT);
+ Optional.ofNullable(data.maxTxRetryTimeMs)
+ .ifPresent(
+ retryTimeMs -> configBuilder.withMaxTransactionRetryTime(retryTimeMs, TimeUnit.MILLISECONDS));
Optional.ofNullable(data.livenessCheckTimeoutMs)
.ifPresent(timeout -> configBuilder.withConnectionLivenessCheckTimeout(timeout, TimeUnit.MILLISECONDS));
Optional.ofNullable(data.maxConnectionPoolSize).ifPresent(configBuilder::withMaxConnectionPoolSize);
@@ -120,7 +119,6 @@ public TestkitResponse process(TestkitState testkitState) {
URI.create(data.uri),
authToken,
config,
- retrySettings,
domainNameResolver,
configureSecuritySettingsBuilder(),
testkitState,
@@ -220,16 +218,14 @@ private org.neo4j.driver.Driver driver(
URI uri,
AuthToken authToken,
Config config,
- RetrySettings retrySettings,
DomainNameResolver domainNameResolver,
SecuritySettings.SecuritySettingsBuilder securitySettingsBuilder,
TestkitState testkitState,
String driverId) {
- RoutingSettings routingSettings = RoutingSettings.DEFAULT;
SecuritySettings securitySettings = securitySettingsBuilder.build();
- SecurityPlan securityPlan = securitySettings.createSecurityPlan(uri.getScheme());
+ SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, uri.getScheme());
return new DriverFactoryWithDomainNameResolver(domainNameResolver, testkitState, driverId)
- .newInstance(uri, authToken, routingSettings, retrySettings, config, securityPlan);
+ .newInstance(uri, authToken, config, securityPlan, null, null);
}
private Optional handleExceptionAsErrorResponse(TestkitState testkitState, RuntimeException e) {