Skip to content

[DE-1010] SSL configuration properties #611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 23, 2025
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
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<relativePath>../release-parent</relativePath>
<groupId>com.arangodb</groupId>
<artifactId>release-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
</parent>

<name>core</name>
Expand Down
35 changes: 35 additions & 0 deletions core/src/main/java/com/arangodb/ArangoDB.java
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ public interface ArangoDB extends ArangoSerdeAccessor {
/**
* Reset the server log levels
* Revert the server's log level settings to the values they had at startup, as determined by the startup options specified on the command-line, a configuration file, and the factory defaults.
*
* @since ArangoDB 3.12
*/
LogLevelEntity resetLogLevels(LogLevelOptions options);
Expand Down Expand Up @@ -484,6 +485,39 @@ public Builder useSsl(final Boolean useSsl) {
return this;
}

/**
* Sets the SSL certificate value as Base64 encoded String
*
* @param sslCertValue the SSL certificate value as Base64 encoded String
* @return {@link ArangoDB.Builder}
*/
public Builder sslCertValue(final String sslCertValue) {
config.setSslCertValue(sslCertValue);
return this;
}

/**
* Sets the SSL Trust manager algorithm
*
* @param sslAlgorithm the name of the SSL Trust manager algorithm
* @return {@link ArangoDB.Builder}
*/
public Builder sslAlgorithm(final String sslAlgorithm) {
config.setSslAlgorithm(sslAlgorithm);
return this;
}

/**
* Sets the SSLContext protocol, default: {@code TLS}
*
* @param sslProtocol the name of the SSLContext protocol
* @return {@link ArangoDB.Builder}
*/
public Builder sslProtocol(final String sslProtocol) {
config.setSslProtocol(sslProtocol);
return this;
}

/**
* Sets the SSL context to be used when {@code true} is passed through {@link #useSsl(Boolean)}.
*
Expand Down Expand Up @@ -716,6 +750,7 @@ public Builder compressionLevel(Integer level) {

/**
* Configuration specific for {@link com.arangodb.internal.net.ProtocolProvider}.
*
* @return {@link ArangoDB.Builder}
*/
public Builder protocolConfig(ProtocolConfig protocolConfig) {
Expand Down
15 changes: 15 additions & 0 deletions core/src/main/java/com/arangodb/config/ArangoConfigProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ public interface ArangoConfigProperties {
String KEY_JWT = "jwt";
String KEY_TIMEOUT = "timeout";
String KEY_USE_SSL = "useSsl";
String KEY_SSL_CERT_VALUE = "sslCertValue";
String KEY_SSL_ALGORITHM = "sslAlgorithm";
String KEY_SSL_PROTOCOL = "sslProtocol";
String KEY_VERIFY_HOST = "verifyHost";
String KEY_CHUNK_SIZE = "chunkSize";
String KEY_PIPELINING = "pipelining";
Expand Down Expand Up @@ -103,6 +106,18 @@ default Optional<Boolean> getUseSsl() {
return Optional.empty();
}

default Optional<String> getSslCertValue() {
return Optional.empty();
}

default Optional<String> getSslAlgorithm() {
return Optional.empty();
}

default Optional<String> getSslProtocol() {
return Optional.empty();
}

default Optional<Boolean> getVerifyHost() {
return Optional.empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public final class ArangoDefaults {
public static final Integer DEFAULT_TIMEOUT = 0;
public static final Long DEFAULT_CONNECTION_TTL_HTTP = 30_000L;
public static final Boolean DEFAULT_USE_SSL = false;
public static final String DEFAULT_SSL_PROTOCOL = "TLS";
public static final Boolean DEFAULT_VERIFY_HOST = true;
public static final Integer DEFAULT_CHUNK_SIZE = 30_000;
public static final Boolean DEFAULT_PIPELINING = false;
Expand Down
48 changes: 48 additions & 0 deletions core/src/main/java/com/arangodb/internal/config/ArangoConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
import com.fasterxml.jackson.databind.Module;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.ByteArrayInputStream;
import java.lang.reflect.InvocationTargetException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
Expand All @@ -30,6 +35,9 @@ public class ArangoConfig {
private String password;
private String jwt;
private Boolean useSsl;
private Optional<String> sslCertValue;
private Optional<String> sslAlgorithm;
private String sslProtocol;
private SSLContext sslContext;
private Boolean verifyHost;
private Integer chunkSize;
Expand Down Expand Up @@ -69,6 +77,9 @@ public void loadProperties(final ArangoConfigProperties properties) {
// FIXME: make jwt field Optional
jwt = properties.getJwt().orElse(null);
useSsl = properties.getUseSsl().orElse(ArangoDefaults.DEFAULT_USE_SSL);
sslCertValue = properties.getSslCertValue();
sslAlgorithm = properties.getSslAlgorithm();
sslProtocol = properties.getSslProtocol().orElse(ArangoDefaults.DEFAULT_SSL_PROTOCOL);
verifyHost = properties.getVerifyHost().orElse(ArangoDefaults.DEFAULT_VERIFY_HOST);
chunkSize = properties.getChunkSize().orElse(ArangoDefaults.DEFAULT_CHUNK_SIZE);
pipelining = properties.getPipelining().orElse(ArangoDefaults.DEFAULT_PIPELINING);
Expand Down Expand Up @@ -151,7 +162,22 @@ public void setUseSsl(Boolean useSsl) {
this.useSsl = useSsl;
}

public void setSslCertValue(String sslCertValue) {
this.sslCertValue = Optional.ofNullable(sslCertValue);
}

public void setSslAlgorithm(String sslAlgorithm) {
this.sslAlgorithm = Optional.ofNullable(sslAlgorithm);
}

public void setSslProtocol(String sslProtocol) {
this.sslProtocol = sslProtocol;
}

public SSLContext getSslContext() {
if (sslContext == null) {
sslContext = createSslContext();
}
return sslContext;
}

Expand Down Expand Up @@ -342,4 +368,26 @@ public ProtocolConfig getProtocolConfig() {
public void setProtocolConfig(ProtocolConfig protocolConfig) {
this.protocolConfig = protocolConfig;
}

private SSLContext createSslContext() {
try {
if (sslCertValue.isPresent()) {
ByteArrayInputStream is = new ByteArrayInputStream(Base64.getDecoder().decode(sslCertValue.get()));
Certificate cert = CertificateFactory.getInstance("X.509").generateCertificate(is);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null);
ks.setCertificateEntry("arangodb", cert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(sslAlgorithm.orElseGet(TrustManagerFactory::getDefaultAlgorithm));
tmf.init(ks);
SSLContext sc = SSLContext.getInstance(sslProtocol);
sc.init(null, tmf.getTrustManagers(), null);
return sc;
} else {
return SSLContext.getDefault();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,21 @@ public Optional<Boolean> getUseSsl() {
return Optional.ofNullable(getProperty(KEY_USE_SSL)).map(Boolean::valueOf);
}

@Override
public Optional<String> getSslCertValue() {
return Optional.ofNullable(getProperty(KEY_SSL_CERT_VALUE));
}

@Override
public Optional<String> getSslAlgorithm() {
return Optional.ofNullable(getProperty(KEY_SSL_ALGORITHM));
}

@Override
public Optional<String> getSslProtocol() {
return Optional.ofNullable(getProperty(KEY_SSL_PROTOCOL));
}

@Override
public Optional<Boolean> getVerifyHost() {
return Optional.ofNullable(getProperty(KEY_VERIFY_HOST)).map(Boolean::valueOf);
Expand Down
2 changes: 1 addition & 1 deletion driver/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<relativePath>../release-parent</relativePath>
<groupId>com.arangodb</groupId>
<artifactId>release-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
</parent>

<name>arangodb-java-driver</name>
Expand Down
2 changes: 1 addition & 1 deletion http-protocol/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<relativePath>../release-parent</relativePath>
<groupId>com.arangodb</groupId>
<artifactId>release-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
</parent>

<name>http-protocol</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map.Entry;
Expand Down Expand Up @@ -169,17 +168,7 @@ private static String getUserAgent() {
}

if (Boolean.TRUE.equals(config.getUseSsl())) {
SSLContext ctx;
if (config.getSslContext() != null) {
ctx = config.getSslContext();
} else {
try {
ctx = SSLContext.getDefault();
} catch (NoSuchAlgorithmException e) {
throw ArangoDBException.of(e);
}
}

SSLContext ctx = config.getSslContext();
webClientOptions
.setSsl(true)
.setUseAlpn(true)
Expand Down
2 changes: 1 addition & 1 deletion jackson-serde-json/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<relativePath>../release-parent</relativePath>
<groupId>com.arangodb</groupId>
<artifactId>release-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
</parent>

<name>jackson-serde-json</name>
Expand Down
2 changes: 1 addition & 1 deletion jackson-serde-vpack/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<relativePath>../release-parent</relativePath>
<groupId>com.arangodb</groupId>
<artifactId>release-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
</parent>

<name>jackson-serde-vpack</name>
Expand Down
2 changes: 1 addition & 1 deletion jsonb-serde/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<relativePath>../release-parent</relativePath>
<groupId>com.arangodb</groupId>
<artifactId>release-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
</parent>

<name>jsonb-serde</name>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>com.arangodb</groupId>
<artifactId>arangodb-java-driver-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
<inceptionYear>2016</inceptionYear>
<modules>
<module>release-parent</module>
Expand Down
2 changes: 1 addition & 1 deletion release-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>com.arangodb</groupId>
<artifactId>arangodb-java-driver-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
</parent>
<packaging>pom</packaging>

Expand Down
2 changes: 1 addition & 1 deletion shaded/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<relativePath>../release-parent</relativePath>
<groupId>com.arangodb</groupId>
<artifactId>release-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
</parent>

<name>arangodb-java-driver-shaded</name>
Expand Down
2 changes: 1 addition & 1 deletion test-functional/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<relativePath>../test-parent</relativePath>
<groupId>com.arangodb</groupId>
<artifactId>test-parent</artifactId>
<version>7.20.0</version>
<version>7.21.0-SNAPSHOT</version>
</parent>

<artifactId>test-functional</artifactId>
Expand Down
31 changes: 31 additions & 0 deletions test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package com.arangodb;

import com.arangodb.config.ArangoConfigProperties;
import com.arangodb.entity.ArangoDBVersion;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
Expand Down Expand Up @@ -55,6 +56,36 @@ void connect(Protocol protocol) {
assertThat(version).isNotNull();
}

@ParameterizedTest
@EnumSource(Protocol.class)
void connectWithCertConf(Protocol protocol) {
assumeTrue(protocol != Protocol.VST);

final ArangoDB arangoDB = new ArangoDB.Builder()
.protocol(protocol)
.host("172.28.0.1", 8529)
.password("test")
.useSsl(true)
.sslCertValue("MIIDezCCAmOgAwIBAgIEeDCzXzANBgkqhkiG9w0BAQsFADBuMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMjAxMTAxMTg1MTE5WhcNMzAxMDMwMTg1MTE5WjBuMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1WiDnd4+uCmMG539ZNZB8NwI0RZF3sUSQGPx3lkqaFTZVEzMZL76HYvdc9Qg7difyKyQ09RLSpMALX9euSseD7bZGnfQH52BnKcT09eQ3wh7aVQ5sN2omygdHLC7X9usntxAfv7NzmvdogNXoJQyY/hSZff7RIqWH8NnAUKkjqOe6Bf5LDbxHKESmrFBxOCOnhcpvZWetwpiRdJVPwUn5P82CAZzfiBfmBZnB7D0l+/6Cv4jMuH26uAIcixnVekBQzl1RgwczuiZf2MGO64vDMMJJWE9ClZF1uQuQrwXF6qwhuP1Hnkii6wNbTtPWlGSkqeutr004+Hzbf8KnRY4PAgMBAAGjITAfMB0GA1UdDgQWBBTBrv9Awynt3C5IbaCNyOW5v4DNkTANBgkqhkiG9w0BAQsFAAOCAQEAIm9rPvDkYpmzpSIhR3VXG9Y71gxRDrqkEeLsMoEyqGnw/zx1bDCNeGg2PncLlW6zTIipEBooixIE9U7KxHgZxBy0Et6EEWvIUmnr6F4F+dbTD050GHlcZ7eOeqYTPYeQC502G1Fo4tdNi4lDP9L9XZpf7Q1QimRH2qaLS03ZFZa2tY7ah/RQqZL8Dkxx8/zc25sgTHVpxoK853glBVBs/ENMiyGJWmAXQayewY3EPt/9wGwV4KmU3dPDleQeXSUGPUISeQxFjy+jCw21pYviWVJTNBA9l5ny3GhEmcnOT/gQHCvVRLyGLMbaMZ4JrPwb+aAtBgrgeiK4xeSMMvrbhw==")
.verifyHost(false)
.build();
final ArangoDBVersion version = arangoDB.getVersion();
assertThat(version).isNotNull();
}

@ParameterizedTest
@EnumSource(Protocol.class)
void connectWithFileProperties(Protocol protocol) {
assumeTrue(protocol != Protocol.VST);

final ArangoDB arangoDB = new ArangoDB.Builder()
.loadProperties(ArangoConfigProperties.fromFile("arangodb-ssl.properties"))
.protocol(protocol)
.build();
final ArangoDBVersion version = arangoDB.getVersion();
assertThat(version).isNotNull();
}

@ParameterizedTest
@EnumSource(Protocol.class)
void connectWithoutValidSslContext(Protocol protocol) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
import com.arangodb.internal.config.ArangoConfig;
import org.junit.jupiter.api.Test;

import javax.net.ssl.SSLContext;

import java.security.NoSuchAlgorithmException;

import static org.assertj.core.api.Assertions.assertThat;

public class ArangoConfigTest {
@Test
void ArangoConfigDefaultValues() {
void ArangoConfigDefaultValues() throws NoSuchAlgorithmException {
ArangoConfig cfg = new ArangoConfig();
assertThat(cfg.getHosts()).isEqualTo(ArangoDefaults.DEFAULT_HOSTS);
assertThat(cfg.getProtocol()).isEqualTo(Protocol.HTTP2_JSON);
Expand All @@ -18,7 +22,7 @@ void ArangoConfigDefaultValues() {
assertThat(cfg.getPassword()).isNull();
assertThat(cfg.getJwt()).isNull();
assertThat(cfg.getUseSsl()).isEqualTo(ArangoDefaults.DEFAULT_USE_SSL);
assertThat(cfg.getSslContext()).isNull();
assertThat(cfg.getSslContext()).isEqualTo(SSLContext.getDefault());
assertThat(cfg.getVerifyHost()).isEqualTo(ArangoDefaults.DEFAULT_VERIFY_HOST);
assertThat(cfg.getChunkSize()).isEqualTo(ArangoDefaults.DEFAULT_CHUNK_SIZE);
assertThat(cfg.getMaxConnections()).isEqualTo(ArangoDefaults.MAX_CONNECTIONS_HTTP2_DEFAULT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

class UserAgentTest extends BaseJunit5 {

private static final String EXPECTED_VERSION = "7.20.0";
private static final String EXPECTED_VERSION = "7.21.0-SNAPSHOT";

private static final boolean SHADED = Boolean.parseBoolean(System.getProperty("shaded"));

Expand Down
Loading