From 5b645b3c566b8f31347c0dc5ba2eeb08872663e2 Mon Sep 17 00:00:00 2001 From: Dmitriy Tverdiakov Date: Thu, 15 Dec 2022 15:07:59 +0000 Subject: [PATCH] Update driver factory --- .../main/java/org/neo4j/driver/Config.java | 28 +- .../java/org/neo4j/driver/GraphDatabase.java | 10 +- .../org/neo4j/driver/SecuritySettings.java | 29 ++ .../neo4j/driver/internal/DriverFactory.java | 34 +- .../internal/InternalSecuritySettings.java | 75 +++++ .../internal/cluster/RoutingSettings.java | 1 - .../retry/ExponentialBackoffRetryLogic.java | 6 +- .../SecurityPlans.java} | 107 ++---- .../java/org/neo4j/driver/ConfigTest.java | 14 +- .../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 +- .../InternalSecuritySettingsTest.java | 134 ++++++++ .../driver/internal/SecuritySettingsTest.java | 318 ------------------ .../ExponentialBackoffRetryLogicTest.java | 46 +-- .../internal/security/SecurityPlans.java | 207 ++++++++++++ .../DriverFactoryWithFixedRetryLogic.java | 3 +- .../driver/internal/util/FixedRetryLogic.java | 3 +- .../backend/messages/requests/NewDriver.java | 25 +- 27 files changed, 561 insertions(+), 584 deletions(-) create mode 100644 driver/src/main/java/org/neo4j/driver/SecuritySettings.java create mode 100644 driver/src/main/java/org/neo4j/driver/internal/InternalSecuritySettings.java rename driver/src/main/java/org/neo4j/driver/internal/{SecuritySettings.java => security/SecurityPlans.java} (58%) create mode 100644 driver/src/test/java/org/neo4j/driver/internal/InternalSecuritySettingsTest.java delete mode 100644 driver/src/test/java/org/neo4j/driver/internal/SecuritySettingsTest.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..ae0e52a2ac 100644 --- a/driver/src/main/java/org/neo4j/driver/Config.java +++ b/driver/src/main/java/org/neo4j/driver/Config.java @@ -32,11 +32,11 @@ import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.logging.Level; -import org.neo4j.driver.internal.SecuritySettings; +import org.neo4j.driver.internal.InternalSecuritySettings; 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; @@ -92,7 +92,7 @@ public final class Config implements Serializable { private final long routingTablePurgeDelayMillis; private final int connectionTimeoutMillis; - private final RetrySettings retrySettings; + private final long maxTransactionRetryTime; private final ServerAddressResolver resolver; private final int eventLoopThreads; @@ -113,7 +113,7 @@ private Config(ConfigBuilder builder) { this.connectionTimeoutMillis = builder.connectionTimeoutMillis; this.routingTablePurgeDelayMillis = builder.routingTablePurgeDelayMillis; - this.retrySettings = builder.retrySettings; + this.maxTransactionRetryTime = builder.maxTransactionRetryTime; this.resolver = builder.resolver; this.fetchSize = builder.fetchSize; @@ -214,16 +214,16 @@ public static Config defaultConfig() { /** * @return the security setting to use when creating connections. */ - SecuritySettings securitySettings() { + public SecuritySettings securitySettings() { return securitySettings; } - RoutingSettings routingSettings() { - return new RoutingSettings(routingTablePurgeDelayMillis); + public long routingTablePurgeDelay() { + return routingTablePurgeDelayMillis; } - RetrySettings retrySettings() { - return retrySettings; + public long maxTransactionRetryTime() { + return maxTransactionRetryTime; } public long fetchSize() { @@ -263,11 +263,11 @@ public static final class ConfigBuilder { private long maxConnectionLifetimeMillis = PoolSettings.DEFAULT_MAX_CONNECTION_LIFETIME; private long connectionAcquisitionTimeoutMillis = PoolSettings.DEFAULT_CONNECTION_ACQUISITION_TIMEOUT; private String userAgent = format("neo4j-java/%s", driverVersion()); - private final SecuritySettings.SecuritySettingsBuilder securitySettingsBuilder = - new SecuritySettings.SecuritySettingsBuilder(); - private long routingTablePurgeDelayMillis = RoutingSettings.DEFAULT.routingTablePurgeDelayMs(); + private final InternalSecuritySettings.SecuritySettingsBuilder securitySettingsBuilder = + new InternalSecuritySettings.SecuritySettingsBuilder(); + 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 maxTransactionRetryTime = ExponentialBackoffRetryLogic.DEFAULT_MAX_RETRY_TIME_MS; private ServerAddressResolver resolver; private MetricsAdapter metricsAdapter = MetricsAdapter.DEV_NULL; private long fetchSize = FetchSizeUtil.DEFAULT_FETCH_SIZE; @@ -553,7 +553,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.maxTransactionRetryTime = maxRetryTimeMs; return this; } 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/SecuritySettings.java b/driver/src/main/java/org/neo4j/driver/SecuritySettings.java new file mode 100644 index 0000000000..c9558014d9 --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/SecuritySettings.java @@ -0,0 +1,29 @@ +/* + * 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; + +import java.io.Serializable; + +public interface SecuritySettings extends Serializable { + // TODO + boolean encrypted(); + + // TODO + Config.TrustStrategy trustStrategy(); +} 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..cdca52f9fb 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,19 @@ public final Driver newInstance( ownsEventLoopGroup = false; } + if (securityPlan == null) { + securityPlan = SecurityPlans.createSecurityPlan(config.securitySettings(), 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.routingTablePurgeDelay(), 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.maxTransactionRetryTime(), eventExecutorGroup, config.logging()); MetricsProvider metricsProvider = getOrCreateMetricsProvider(config, createClock()); ConnectionPool connectionPool = createConnectionPool( @@ -113,7 +111,7 @@ public final Driver newInstance( metricsProvider, config, ownsEventLoopGroup, - newRoutingSettings.routingContext()); + routingSettings.routingContext()); return createDriver( uri, @@ -121,7 +119,7 @@ public final Driver newInstance( address, connectionPool, eventExecutorGroup, - newRoutingSettings, + routingSettings, retryLogic, metricsProvider, rediscoverySupplier, @@ -354,8 +352,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/InternalSecuritySettings.java b/driver/src/main/java/org/neo4j/driver/internal/InternalSecuritySettings.java new file mode 100644 index 0000000000..f94d0a837a --- /dev/null +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalSecuritySettings.java @@ -0,0 +1,75 @@ +/* + * 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; + +import org.neo4j.driver.Config; + +public class InternalSecuritySettings implements org.neo4j.driver.SecuritySettings { + private static final long serialVersionUID = 4494615367164106576L; + + private static final boolean DEFAULT_ENCRYPTED = false; + private static final Config.TrustStrategy DEFAULT_TRUST_STRATEGY = Config.TrustStrategy.trustSystemCertificates(); + public static final InternalSecuritySettings DEFAULT = + new InternalSecuritySettings(DEFAULT_ENCRYPTED, DEFAULT_TRUST_STRATEGY); + private final boolean encrypted; + private final Config.TrustStrategy trustStrategy; + + public InternalSecuritySettings(boolean encrypted, Config.TrustStrategy trustStrategy) { + this.encrypted = encrypted; + this.trustStrategy = trustStrategy == null ? DEFAULT_TRUST_STRATEGY : trustStrategy; + } + + public boolean encrypted() { + return encrypted; + } + + public Config.TrustStrategy trustStrategy() { + return trustStrategy; + } + + public static class SecuritySettingsBuilder { + private boolean isCustomized = false; + private boolean encrypted; + private Config.TrustStrategy trustStrategy; + + public SecuritySettingsBuilder withEncryption() { + encrypted = true; + isCustomized = true; + return this; + } + + public SecuritySettingsBuilder withoutEncryption() { + encrypted = false; + isCustomized = true; + return this; + } + + public SecuritySettingsBuilder withTrustStrategy(Config.TrustStrategy strategy) { + trustStrategy = strategy; + isCustomized = true; + return this; + } + + public InternalSecuritySettings build() { + return isCustomized + ? new InternalSecuritySettings(encrypted, trustStrategy) + : InternalSecuritySettings.DEFAULT; + } + } +} 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..ec6464f74b 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; 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/SecuritySettings.java b/driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlans.java similarity index 58% rename from driver/src/main/java/org/neo4j/driver/internal/SecuritySettings.java rename to driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlans.java index c86daeeb88..82b3141e28 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/SecuritySettings.java +++ b/driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlans.java @@ -16,82 +16,63 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.neo4j.driver.internal; +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.io.Serializable; import java.security.GeneralSecurityException; import org.neo4j.driver.Config; import org.neo4j.driver.RevocationCheckingStrategy; +import org.neo4j.driver.SecuritySettings; import org.neo4j.driver.exceptions.ClientException; -import org.neo4j.driver.internal.security.SecurityPlan; -import org.neo4j.driver.internal.security.SecurityPlanImpl; +import org.neo4j.driver.internal.InternalSecuritySettings; +import org.neo4j.driver.internal.Scheme; -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); - private final boolean encrypted; - private final Config.TrustStrategy trustStrategy; - - public SecuritySettings(boolean encrypted, Config.TrustStrategy trustStrategy) { - this.encrypted = encrypted; - this.trustStrategy = trustStrategy == null ? DEFAULT_TRUST_STRATEGY : trustStrategy; - } - - public boolean encrypted() { - return encrypted; - } - - 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) { +public class SecurityPlans { + public static SecurityPlan createSecurityPlan(SecuritySettings settings, String uriScheme) { Scheme.validateScheme(uriScheme); try { if (isSecurityScheme(uriScheme)) { - assertSecuritySettingsNotUserConfigured(uriScheme); + assertSecuritySettingsNotUserConfigured(settings, uriScheme); return createSecurityPlanFromScheme(uriScheme); } else { - return createSecurityPlanImpl(encrypted, trustStrategy); + return createSecurityPlanImpl(settings.encrypted(), settings.trustStrategy()); } } catch (GeneralSecurityException | IOException ex) { throw new ClientException("Unable to establish SSL parameters", ex); } } - private void assertSecuritySettingsNotUserConfigured(String uriScheme) { - if (isCustomized()) { + 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)); } } - private SecurityPlan createSecurityPlanFromScheme(String scheme) throws GeneralSecurityException, IOException { + public static boolean isCustomized(SecuritySettings securitySettings) { + return !(InternalSecuritySettings.DEFAULT.encrypted() == securitySettings.encrypted() + && hasEqualTrustStrategy(securitySettings)); + } + + private static boolean hasEqualTrustStrategy(SecuritySettings settings) { + Config.TrustStrategy t1 = InternalSecuritySettings.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 { @@ -125,32 +106,4 @@ private static SecurityPlan createSecurityPlanImpl(boolean encrypted, Config.Tru return insecure(); } } - - public static class SecuritySettingsBuilder { - private boolean isCustomized = false; - private boolean encrypted; - private Config.TrustStrategy trustStrategy; - - public SecuritySettingsBuilder withEncryption() { - encrypted = true; - isCustomized = true; - return this; - } - - public SecuritySettingsBuilder withoutEncryption() { - encrypted = false; - isCustomized = true; - return this; - } - - public SecuritySettingsBuilder withTrustStrategy(Config.TrustStrategy strategy) { - trustStrategy = strategy; - isCustomized = true; - return this; - } - - public SecuritySettings build() { - return isCustomized ? new SecuritySettings(encrypted, trustStrategy) : SecuritySettings.DEFAULT; - } - } } diff --git a/driver/src/test/java/org/neo4j/driver/ConfigTest.java b/driver/src/test/java/org/neo4j/driver/ConfigTest.java index 468e222ad8..859084182e 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.maxTransactionRetryTime()); } @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.maxTransactionRetryTime()); } @Test @@ -413,11 +412,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.maxTransactionRetryTime(), verify.maxTransactionRetryTime()); assertEquals(config.fetchSize(), verify.fetchSize()); assertEquals(config.eventLoopThreads(), verify.eventLoopThreads()); assertEquals(config.encrypted(), verify.encrypted()); @@ -434,9 +430,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.maxTransactionRetryTime(), verify.maxTransactionRetryTime()); 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/InternalSecuritySettingsTest.java b/driver/src/test/java/org/neo4j/driver/internal/InternalSecuritySettingsTest.java new file mode 100644 index 0000000000..4d5e062038 --- /dev/null +++ b/driver/src/test/java/org/neo4j/driver/internal/InternalSecuritySettingsTest.java @@ -0,0 +1,134 @@ +/* + * 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; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.neo4j.driver.internal.security.SecurityPlans.isCustomized; + +import java.io.File; +import java.io.IOException; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.neo4j.driver.Config; +import org.neo4j.driver.testutil.TestUtil; + +class InternalSecuritySettingsTest { + @Nested + class SerializationTests { + @Test + void defaultSettingsShouldNotBeCustomizedWhenReadBack() throws IOException, ClassNotFoundException { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder().build(); + + assertFalse(isCustomized(securitySettings)); + + InternalSecuritySettings verify = + TestUtil.serializeAndReadBack(securitySettings, InternalSecuritySettings.class); + + assertFalse(isCustomized(verify)); + } + + @Test + void defaultsShouldBeCheckCorrect() throws IOException, ClassNotFoundException { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder() + .withoutEncryption() + .withTrustStrategy(Config.TrustStrategy.trustSystemCertificates()) + .build(); + + // The settings are still equivalent to the defaults, even if the builder has been used. It is not + // customized. + assertFalse(isCustomized(securitySettings)); + + InternalSecuritySettings verify = + TestUtil.serializeAndReadBack(securitySettings, InternalSecuritySettings.class); + + assertFalse(isCustomized(verify)); + } + + @Test + void shouldReadBackChangedEncryption() throws IOException, ClassNotFoundException { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder() + .withEncryption() + .withTrustStrategy(Config.TrustStrategy.trustSystemCertificates()) + .build(); + + assertTrue(isCustomized(securitySettings)); + assertTrue(securitySettings.encrypted()); + + InternalSecuritySettings verify = + TestUtil.serializeAndReadBack(securitySettings, InternalSecuritySettings.class); + + assertTrue(isCustomized(verify)); + assertTrue(securitySettings.encrypted()); + } + + @Test + void shouldReadBackChangedStrategey() throws IOException, ClassNotFoundException { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder() + .withoutEncryption() + .withTrustStrategy(Config.TrustStrategy.trustAllCertificates()) + .build(); + + // The settings are still equivalent to the defaults, even if the builder has been used. It is not + // customized. + assertTrue(isCustomized(securitySettings)); + assertFalse(securitySettings.encrypted()); + assertEquals( + Config.TrustStrategy.trustAllCertificates().strategy(), + securitySettings.trustStrategy().strategy()); + + InternalSecuritySettings verify = + TestUtil.serializeAndReadBack(securitySettings, InternalSecuritySettings.class); + + assertTrue(isCustomized(verify)); + assertFalse(securitySettings.encrypted()); + assertEquals( + Config.TrustStrategy.trustAllCertificates().strategy(), + securitySettings.trustStrategy().strategy()); + } + + @Test + void shouldReadBackChangedCertFile() throws IOException, ClassNotFoundException { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder() + .withoutEncryption() + .withTrustStrategy(Config.TrustStrategy.trustCustomCertificateSignedBy(new File("some.cert"))) + .build(); + + // The settings are still equivalent to the defaults, even if the builder has been used. It is not + // customized. + assertTrue(isCustomized(securitySettings)); + assertFalse(securitySettings.encrypted()); + assertEquals( + Config.TrustStrategy.trustCustomCertificateSignedBy(new File("some.cert")) + .strategy(), + securitySettings.trustStrategy().strategy()); + + InternalSecuritySettings verify = + TestUtil.serializeAndReadBack(securitySettings, InternalSecuritySettings.class); + + assertTrue(isCustomized(verify)); + assertFalse(securitySettings.encrypted()); + assertEquals( + Config.TrustStrategy.trustCustomCertificateSignedBy(new File("some.cert")) + .strategy(), + securitySettings.trustStrategy().strategy()); + } + } +} diff --git a/driver/src/test/java/org/neo4j/driver/internal/SecuritySettingsTest.java b/driver/src/test/java/org/neo4j/driver/internal/SecuritySettingsTest.java deleted file mode 100644 index 86c0688f5e..0000000000 --- a/driver/src/test/java/org/neo4j/driver/internal/SecuritySettingsTest.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * 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; - -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.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(); - - assertFalse(isCustomized(securitySettings)); - - SecuritySettings verify = TestUtil.serializeAndReadBack(securitySettings, SecuritySettings.class); - - assertFalse(isCustomized(verify)); - } - - @Test - void defaultsShouldBeCheckCorrect() throws IOException, ClassNotFoundException { - SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder() - .withoutEncryption() - .withTrustStrategy(Config.TrustStrategy.trustSystemCertificates()) - .build(); - - // The settings are still equivalent to the defaults, even if the builder has been used. It is not - // customized. - assertFalse(isCustomized(securitySettings)); - - SecuritySettings verify = TestUtil.serializeAndReadBack(securitySettings, SecuritySettings.class); - - assertFalse(isCustomized(verify)); - } - - @Test - void shouldReadBackChangedEncryption() throws IOException, ClassNotFoundException { - SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder() - .withEncryption() - .withTrustStrategy(Config.TrustStrategy.trustSystemCertificates()) - .build(); - - assertTrue(isCustomized(securitySettings)); - assertTrue(securitySettings.encrypted()); - - SecuritySettings verify = TestUtil.serializeAndReadBack(securitySettings, SecuritySettings.class); - - assertTrue(isCustomized(verify)); - assertTrue(securitySettings.encrypted()); - } - - @Test - void shouldReadBackChangedStrategey() throws IOException, ClassNotFoundException { - SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder() - .withoutEncryption() - .withTrustStrategy(Config.TrustStrategy.trustAllCertificates()) - .build(); - - // The settings are still equivalent to the defaults, even if the builder has been used. It is not - // customized. - assertTrue(isCustomized(securitySettings)); - assertFalse(securitySettings.encrypted()); - assertEquals( - Config.TrustStrategy.trustAllCertificates().strategy(), - securitySettings.trustStrategy().strategy()); - - SecuritySettings verify = TestUtil.serializeAndReadBack(securitySettings, SecuritySettings.class); - - assertTrue(isCustomized(verify)); - assertFalse(securitySettings.encrypted()); - assertEquals( - Config.TrustStrategy.trustAllCertificates().strategy(), - securitySettings.trustStrategy().strategy()); - } - - @Test - void shouldReadBackChangedCertFile() throws IOException, ClassNotFoundException { - SecuritySettings securitySettings = new SecuritySettings.SecuritySettingsBuilder() - .withoutEncryption() - .withTrustStrategy(Config.TrustStrategy.trustCustomCertificateSignedBy(new File("some.cert"))) - .build(); - - // The settings are still equivalent to the defaults, even if the builder has been used. It is not - // customized. - assertTrue(isCustomized(securitySettings)); - assertFalse(securitySettings.encrypted()); - assertEquals( - Config.TrustStrategy.trustCustomCertificateSignedBy(new File("some.cert")) - .strategy(), - securitySettings.trustStrategy().strategy()); - - SecuritySettings verify = TestUtil.serializeAndReadBack(securitySettings, SecuritySettings.class); - - assertTrue(isCustomized(verify)); - assertFalse(securitySettings.encrypted()); - assertEquals( - Config.TrustStrategy.trustCustomCertificateSignedBy(new File("some.cert")) - .strategy(), - securitySettings.trustStrategy().strategy()); - } - } -} 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..a94e89aa14 --- /dev/null +++ b/driver/src/test/java/org/neo4j/driver/internal/security/SecurityPlans.java @@ -0,0 +1,207 @@ +/* + * 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.InternalSecuritySettings; + +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) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder().build(); + + SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme); + + assertTrue(securityPlan.requiresEncryption()); + } + + @ParameterizedTest + @MethodSource("systemCertSchemes") + void testSystemCertCompatibleConfiguration(String scheme) throws Exception { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.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 { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder().build(); + + SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme); + + assertTrue(securityPlan.requiresEncryption()); + assertFalse(securityPlan.requiresHostnameVerification()); + } + + @ParameterizedTest + @MethodSource("allSecureSchemes") + void testThrowsOnUserCustomizedEncryption(String scheme) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.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) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.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) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.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) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder().build(); + + SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme); + + assertFalse(securityPlan.requiresEncryption()); + } + + @ParameterizedTest + @MethodSource("unencryptedSchemes") + void testConfiguredEncryption(String scheme) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder() + .withEncryption() + .build(); + + SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme); + + assertTrue(securityPlan.requiresEncryption()); + } + + @ParameterizedTest + @MethodSource("unencryptedSchemes") + void testConfiguredAllCertificates(String scheme) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.SecuritySettingsBuilder() + .withEncryption() + .withTrustStrategy(Config.TrustStrategy.trustAllCertificates()) + .build(); + + SecurityPlan securityPlan = SecurityPlans.createSecurityPlan(securitySettings, scheme); + + assertTrue(securityPlan.requiresEncryption()); + } + + @ParameterizedTest + @MethodSource("unencryptedSchemes") + void testConfigureStrictRevocationChecking(String scheme) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.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) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.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) { + InternalSecuritySettings securitySettings = new InternalSecuritySettings.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..aca19f27ad 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 @@ -49,11 +49,10 @@ import org.neo4j.driver.internal.DefaultDomainNameResolver; 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.InternalSecuritySettings; 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,6 @@ 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.livenessCheckTimeoutMs) .ifPresent(timeout -> configBuilder.withConnectionLivenessCheckTimeout(timeout, TimeUnit.MILLISECONDS)); Optional.ofNullable(data.maxConnectionPoolSize).ifPresent(configBuilder::withMaxConnectionPoolSize); @@ -120,7 +116,6 @@ public TestkitResponse process(TestkitState testkitState) { URI.create(data.uri), authToken, config, - retrySettings, domainNameResolver, configureSecuritySettingsBuilder(), testkitState, @@ -220,16 +215,14 @@ private org.neo4j.driver.Driver driver( URI uri, AuthToken authToken, Config config, - RetrySettings retrySettings, DomainNameResolver domainNameResolver, - SecuritySettings.SecuritySettingsBuilder securitySettingsBuilder, + InternalSecuritySettings.SecuritySettingsBuilder securitySettingsBuilder, TestkitState testkitState, String driverId) { - RoutingSettings routingSettings = RoutingSettings.DEFAULT; - SecuritySettings securitySettings = securitySettingsBuilder.build(); - SecurityPlan securityPlan = securitySettings.createSecurityPlan(uri.getScheme()); + InternalSecuritySettings securitySettings = securitySettingsBuilder.build(); + 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) { @@ -249,9 +242,9 @@ private Optional handleExceptionAsErrorResponse(TestkitState te return response; } - private SecuritySettings.SecuritySettingsBuilder configureSecuritySettingsBuilder() { - SecuritySettings.SecuritySettingsBuilder securitySettingsBuilder = - new SecuritySettings.SecuritySettingsBuilder(); + private InternalSecuritySettings.SecuritySettingsBuilder configureSecuritySettingsBuilder() { + InternalSecuritySettings.SecuritySettingsBuilder securitySettingsBuilder = + new InternalSecuritySettings.SecuritySettingsBuilder(); if (data.encrypted) { securitySettingsBuilder.withEncryption(); } else {