Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public class Item {

// Init a database instance and choose the binding (builtin). Configure connection pool size and connection
// timeout. Database should be created explicitly via reindexer_tool.
// To connect to Reindexer with TLS, use cprotos:// protocol with default port 6535.
// Use ReindexerConfiguration#sslSocketFactory to provide a custom SSLSocketFactory.
Reindexer db = ReindexerConfiguration.builder()
.url("cproto://localhost:6534/testdb")
.connectionPoolSize(1)
Expand Down Expand Up @@ -354,3 +356,21 @@ Depends on amount changes in transaction there are 2 possible Commit strategies:
2. Transaction object holds Reindexer's resources, therefore application should explicitly call `tx.rollback` or `tx.commit`, otherwise resources will leak.
3. It is safe to call `tx.rollback` after `tx.commit`.
4. It is possible to call Query from transaction by call `tx.query().execute(); ...`. Only read-committed isolation is available. Changes made in active transaction is invisible to current and another transactions.

### Development notes

To run tests locally, you need to install Reindexer using a package manager for your OS.
Cprotos protocol tests require Reindexer to be built with TLS support, and ssl certificate and key must be placed in
src/test/resources, to generate a new valid certificate run the following commands:

```bash
cd src/test/resources
# Generates a certificate key (not needed if you already have one).
openssl genrsa -out builtin-server.key 2048
# Generates a self-signed certificate using the provided key;
# Prompts to fill certificate information e.g. CN=localhost;
# The certificate will be valid for 10 years.
openssl req -new -x509 -key builtin-server.key -out builtin-server.crt -days 3650
# Import the certificate into the Java keystore and save it as a JKS file.
keytool -importcert -alias builtin-server -file builtin-server.crt -keystore builtin-server.jks -storepass password -noprompt
```
16 changes: 15 additions & 1 deletion builtin-adapter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)

project(builtin-adapter)

Expand All @@ -17,3 +17,17 @@ add_library(${TARGET} SHARED BuiltinAdapter.cpp)
include_directories(${JNI_INCLUDE_DIRS} ${REINDEXER_INCLUDE_DIRS})

target_link_libraries(${TARGET} reindexer_server_library reindexer_server_resources ${REINDEXER_LIBRARIES})

# Workaround for macOS to propagate a correct OpenSSL lib path to Reindexer.
if(APPLE)
find_package(OpenSSL)
if(OpenSSL_FOUND)
if(NOT DEFINED OPENSSL_LIB_PATH)
get_filename_component(OPENSSL_LIB_PATH ${OPENSSL_CRYPTO_LIBRARY} DIRECTORY)
endif()
set_target_properties(${TARGET} PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH ${OPENSSL_LIB_PATH}
)
endif()
endif()
9 changes: 6 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@
<!-- Activate the use of TCP to transmit events to the plugin. -->
<forkNode implementation="org.apache.maven.plugin.surefire.extensions.SurefireForkNodeFactory" />
<groups>${tests}</groups>
<systemPropertyVariables>
<javax.net.ssl.trustStore>${project.basedir}/src/test/resources/builtin-server.jks</javax.net.ssl.trustStore>
<javax.net.ssl.trustStorePassword>password</javax.net.ssl.trustStorePassword>
</systemPropertyVariables>
</configuration>
</plugin>

Expand Down Expand Up @@ -175,13 +179,12 @@
</plugin>

<plugin>
<groupId>com.googlecode.cmake-maven-project</groupId>
<groupId>io.github.cmake-maven-plugin</groupId>
<artifactId>cmake-maven-plugin</artifactId>
<version>3.19.2-b1</version>
<version>4.0.3-b1</version>
<configuration>
<generator>Unix Makefiles</generator>
<sourcePath>${cmake.source.directory}</sourcePath>
<targetPath>${cmake.binary.directory}</targetPath>
<projectDirectory>${cmake.binary.directory}</projectDirectory>
</configuration>
<executions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import java.util.Objects;
import java.util.function.Consumer;

import javax.net.ssl.SSLSocketFactory;

/**
* Represents approach for bootstrapping Reindexer.
*/
Expand All @@ -54,6 +56,8 @@ public final class ReindexerConfiguration {

private String serverConfigFile = "default-builtin-server-config.yml";

private SSLSocketFactory sslSocketFactory;

private ReindexerConfiguration() {

}
Expand Down Expand Up @@ -161,6 +165,17 @@ public ReindexerConfiguration serverConfigFile(String serverConfigFile) {
return this;
}

/**
* Configure an {@link SSLSocketFactory}.
*
* @param sslSocketFactory the {@link SSLSocketFactory} to use
* @return the {@link ReindexerConfiguration} for further customizations
*/
public ReindexerConfiguration sslSocketFactory(SSLSocketFactory sslSocketFactory) {
this.sslSocketFactory = sslSocketFactory;
return this;
}

/**
* Build and return reindexer connector instance.
*
Expand All @@ -186,18 +201,23 @@ public Reindexer getReindexer() {

private Binding getBinding(String protocol, List<URI> uris) {
switch (protocol) {
case "cprotos":
if (sslSocketFactory == null) {
sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
}
case "cproto":
DataSourceConfiguration dataSourceConfig = DataSourceConfiguration.builder()
.urls(urls)
.allowUnlistedDataSource(allowUnlistedDataSource)
.sslSocketFactory(sslSocketFactory)
.build();
return new Cproto(dataSourceFactory, dataSourceConfig, connectionPoolSize, requestTimeout);
case "builtin":
return new Builtin(uris.get(0), requestTimeout);
case "builtinserver":
return new BuiltinServer(uris.get(0), serverConfigFile, serverStartupTimeout, requestTimeout);
default:
throw new UnimplementedException("Protocol: '" + protocol + "' is not suppored");
throw new UnimplementedException("Protocol: '" + protocol + "' is not supported");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.util.List;
import java.util.Objects;

import javax.net.ssl.SSLSocketFactory;

/**
* A {@link DataSource} configuration.
*/
Expand All @@ -37,6 +39,11 @@ public class DataSourceConfiguration {
*/
private final boolean allowUnlistedDataSource;

/**
* An {@link SSLSocketFactory} to connect to Reindexer using cprotos (SSL/TLS) protocol.
*/
private final SSLSocketFactory sslSocketFactory;

/**
* An index of the current active data source.
*/
Expand All @@ -46,6 +53,7 @@ private DataSourceConfiguration(Builder builder) {
urls = builder.urls;
allowUnlistedDataSource = builder.allowUnlistedDataSource;
active = builder.active;
sslSocketFactory = builder.sslSocketFactory;
}

public static Builder builder() {
Expand All @@ -69,6 +77,15 @@ public boolean isAllowUnlistedDataSource() {
return allowUnlistedDataSource;
}

/**
* Returns an {@link SSLSocketFactory} to connect to Reindexer using cprotos (SSL/TLS) protocol.
*
* @return the {@link SSLSocketFactory} to use
*/
public SSLSocketFactory getSslSocketFactory() {
return sslSocketFactory;
}

/**
* Returns the index of the current active data source.
*
Expand Down Expand Up @@ -102,6 +119,11 @@ public static class Builder {
*/
private boolean allowUnlistedDataSource = true;

/**
* An {@link SSLSocketFactory} to connect to Reindexer using cprotos (SSL/TLS) protocol.
*/
private SSLSocketFactory sslSocketFactory;

/**
* An index of the current active data source.
*/
Expand Down Expand Up @@ -157,6 +179,17 @@ public Builder allowUnlistedDataSource(boolean allowUnlistedDataSource) {
return this;
}

/**
* Configure an {@link SSLSocketFactory} to connect to Reindexer using cprotos (TLS) protocol.
*
* @param sslSocketFactory the {@link SSLSocketFactory} to use
* @return the {@link Builder} for further customizations
*/
public Builder sslSocketFactory(SSLSocketFactory sslSocketFactory) {
this.sslSocketFactory = sslSocketFactory;
return this;
}

/**
* Build and return a {@link DataSource} configuration.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public enum DataSourceFactoryStrategy implements DataSourceFactory {
public DataSource getDataSource(DataSourceConfiguration configuration) {
List<String> urls = configuration.getUrls();
configuration.setActive((configuration.getActive() + 1) % urls.size());
return new PhysicalDataSource(urls.get(configuration.getActive()));
return new PhysicalDataSource(urls.get(configuration.getActive()), configuration.getSslSocketFactory());
}
},

Expand All @@ -55,7 +55,7 @@ public DataSource getDataSource(DataSourceConfiguration configuration) {
public DataSource getDataSource(DataSourceConfiguration configuration) {
List<String> urls = configuration.getUrls();
configuration.setActive(ThreadLocalRandom.current().nextInt(urls.size()));
return new PhysicalDataSource(urls.get(configuration.getActive()));
return new PhysicalDataSource(urls.get(configuration.getActive()), configuration.getSslSocketFactory());
}
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import static ru.rt.restream.reindexer.binding.Consts.APP_PROPERTY_NAME;
import static ru.rt.restream.reindexer.binding.Consts.BINDING_CAPABILITY_COMPLEX_RANK;
import static ru.rt.restream.reindexer.binding.Consts.BINDING_CAPABILITY_NAMESPACE_INCARNATIONS;
Expand Down Expand Up @@ -106,9 +109,18 @@ public class PhysicalConnection implements Connection {
private final ScheduledFuture<?> writeTaskFuture;

public PhysicalConnection(String host, int port, String user, String password, String database,
SSLSocketFactory sslSocketFactory,
Duration requestTimeout, ScheduledExecutorService scheduler) {
try {
clientSocket = new Socket(host, port);
if (sslSocketFactory != null) {
LOGGER.debug("rx: using SSL/TLS connection to {}:{}", host, port);
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(host, port);
// Fail fast if SSL/TLS handshake fails.
sslSocket.startHandshake();
clientSocket = sslSocket;
} else {
clientSocket = new Socket(host, port);
}
output = new DataOutputStream(clientSocket.getOutputStream());
input = new DataInputStream(clientSocket.getInputStream());
timeout = requestTimeout;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import java.time.Duration;
import java.util.concurrent.ScheduledThreadPoolExecutor;

import javax.net.ssl.SSLSocketFactory;

/**
* A {@link DataSource} that creates a {@link PhysicalConnection}.
*/
Expand All @@ -35,12 +37,27 @@ public class PhysicalDataSource implements DataSource {

private final String database;

private final SSLSocketFactory sslSocketFactory;

/**
* Creates an instance.
*
* @param url the URL to use
* @deprecated Use {@link #PhysicalDataSource(String, SSLSocketFactory)}
* to connect to Reindexer using cprotos (SSL/TLS) protocol.
*/
@Deprecated
public PhysicalDataSource(String url) {
this(url, null);
}

/**
* Creates an instance.
*
* @param url the URL to use
* @param sslSocketFactory the {@link SSLSocketFactory} socket factory to use
*/
public PhysicalDataSource(String url, SSLSocketFactory sslSocketFactory) {
URI uri = URI.create(url);
host = uri.getHost();
port = uri.getPort();
Expand All @@ -58,11 +75,12 @@ public PhysicalDataSource(String url) {
password = "";
}
database = uri.getPath().substring(1);
this.sslSocketFactory = sslSocketFactory;
}

@Override
public Connection getConnection(Duration timeout, ScheduledThreadPoolExecutor scheduler) {
return new PhysicalConnection(host, port, user, password, database, timeout, scheduler);
return new PhysicalConnection(host, port, user, password, database, sslSocketFactory, timeout, scheduler);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2020 Restream
*
* 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 ru.rt.restream.reindexer.connector;

import org.junit.jupiter.api.BeforeAll;
import ru.rt.restream.category.CprotoTest;
import ru.rt.restream.reindexer.db.DbLocator;
import ru.rt.restream.reindexer.db.DbLocator.Type;

/**
* Tests for Cprotos (SSL/TLS) protocol implementation.
*/
@CprotoTest
public class CprotosReindexerTest extends ReindexerTest {

@BeforeAll
@Override
protected void initDb() {
db = DbLocator.getDb(Type.CPROTOS);
}

}
2 changes: 1 addition & 1 deletion src/test/java/ru/rt/restream/reindexer/db/DbBaseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public abstract class DbBaseTest {
* Initializes the Reindexer instance before all tests.
*/
@BeforeAll
void initDb() {
protected void initDb() {
if (this.getClass().isAnnotationPresent(CprotoTest.class)) {
db = DbLocator.getDb(CPROTO);
} else if (this.getClass().isAnnotationPresent(BuiltinTest.class)) {
Expand Down
Loading