Skip to content

Commit

Permalink
cassandra: adds CASSANDRA_SSL_HOSTNAME_VALIDATION (#3701)
Browse files Browse the repository at this point in the history
This adds `CASSANDRA_SSL_HOSTNAME_VALIDATION` with the same behavior as defined in cassandra's [SSL_HOSTNAME_VALIDATION](https://github.com/apache/cassandra-java-driver/blob/8d5849cb38995b312f29314d18256c0c3e94cf07/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java#L230), with the same default value of true.

Signed-off-by: Adrian Cole <[email protected]>
Co-authored-by: Priya Sharma <[email protected]>
  • Loading branch information
codefromthecrypt and Priya Sharma authored Jan 23, 2024
1 parent 41b4a37 commit 899170c
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 46 deletions.
1 change: 1 addition & 0 deletions zipkin-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ and applies when `STORAGE_TYPE` is set to `cassandra3`:
* `CASSANDRA_ENSURE_SCHEMA`: Ensuring cassandra has the latest schema. If enabled tries to execute scripts in the classpath prefixed with `cassandra-schema-cql3`. Defaults to true
* `CASSANDRA_USERNAME` and `CASSANDRA_PASSWORD`: Cassandra authentication. Will throw an exception on startup if authentication fails. No default
* `CASSANDRA_USE_SSL`: Requires `javax.net.ssl.trustStore` and `javax.net.ssl.trustStorePassword`, defaults to false.
* `CASSANDRA_SSL_HOSTNAME_VALIDATION`: Controls validation of Cassandra server hostname. defaults to true.

The following are tuning parameters which may not concern all users:

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 The OpenZipkin Authors
* Copyright 2015-2024 The OpenZipkin Authors
*
* 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
Expand Down Expand Up @@ -43,14 +43,10 @@
// This component is named .*Cassandra3.* even though the package already says cassandra3 because
// Spring Boot configuration endpoints only printout the simple name of the class
public class ZipkinCassandra3StorageConfiguration {

@Bean SessionFactory sessionFactory() {
return SessionFactory.DEFAULT;
}

@Bean
@ConditionalOnMissingBean
StorageComponent storage(
@Bean @ConditionalOnMissingBean StorageComponent storage(
ZipkinCassandra3StorageProperties properties,
SessionFactory sessionFactory,
@Value("${zipkin.storage.strict-trace-id:true}") boolean strictTraceId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 The OpenZipkin Authors
* Copyright 2015-2024 The OpenZipkin Authors
*
* 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
Expand Down Expand Up @@ -27,6 +27,7 @@ class ZipkinCassandra3StorageProperties implements Serializable { // for Spark j
private int maxConnections = 8;
private boolean ensureSchema = true;
private boolean useSsl = false;
private boolean sslHostnameValidation = true;
private String username;
private String password;
/** See {@link CassandraStorage.Builder#indexFetchMultiplier(int)} */
Expand Down Expand Up @@ -80,6 +81,14 @@ public void setUseSsl(boolean useSsl) {
this.useSsl = useSsl;
}

public boolean isSslHostnameValidation() {
return sslHostnameValidation;
}

public void setSslHostnameValidation(boolean sslHostnameValidation) {
this.sslHostnameValidation = sslHostnameValidation;
}

public String getUsername() {
return username;
}
Expand Down Expand Up @@ -112,6 +121,7 @@ public CassandraStorage.Builder toBuilder() {
.maxConnections(maxConnections)
.ensureSchema(ensureSchema)
.useSsl(useSsl)
.sslHostnameValidation(sslHostnameValidation)
.username(username)
.password(password)
.indexFetchMultiplier(indexFetchMultiplier);
Expand Down
27 changes: 2 additions & 25 deletions zipkin-server/src/main/resources/zipkin-server-shared.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,31 +115,6 @@ zipkin:
mem:
# Maximum number of spans to keep in memory. When exceeded, oldest traces (and their spans) will be purged.
max-spans: ${MEM_MAX_SPANS:500000}
cassandra:
# Comma separated list of host addresses part of Cassandra cluster. Ports default to 9042 but you can also specify a custom port with 'host:port'.
contact-points: ${CASSANDRA_CONTACT_POINTS:localhost}
# Name of the datacenter that will be considered "local" for load balancing.
local-dc: ${CASSANDRA_LOCAL_DC:datacenter1}
# Will throw an exception on startup if authentication fails.
username: ${CASSANDRA_USERNAME:}
password: ${CASSANDRA_PASSWORD:}
keyspace: ${CASSANDRA_KEYSPACE:zipkin}
# Max pooled connections per datacenter-local host.
max-connections: ${CASSANDRA_MAX_CONNECTIONS:8}
# Ensuring that schema exists, if enabled tries to execute script /zipkin-cassandra-core/resources/cassandra-schema.cql.
ensure-schema: ${CASSANDRA_ENSURE_SCHEMA:true}
# 7 days in seconds
span-ttl: ${CASSANDRA_SPAN_TTL:604800}
# 3 days in seconds
index-ttl: ${CASSANDRA_INDEX_TTL:259200}
# the maximum trace index metadata entries to cache
index-cache-max: ${CASSANDRA_INDEX_CACHE_MAX:100000}
# how long to cache index metadata about a trace. 1 minute in seconds
index-cache-ttl: ${CASSANDRA_INDEX_CACHE_TTL:60}
# how many more index rows to fetch than the user-supplied query limit
index-fetch-multiplier: ${CASSANDRA_INDEX_FETCH_MULTIPLIER:3}
# Using ssl for connection, rely on Keystore
use-ssl: ${CASSANDRA_USE_SSL:false}
cassandra3:
# Comma separated list of host addresses part of Cassandra cluster. Ports default to 9042 but you can also specify a custom port with 'host:port'.
contact-points: ${CASSANDRA_CONTACT_POINTS:localhost}
Expand All @@ -157,6 +132,8 @@ zipkin:
index-fetch-multiplier: ${CASSANDRA_INDEX_FETCH_MULTIPLIER:3}
# Using ssl for connection, rely on Keystore
use-ssl: ${CASSANDRA_USE_SSL:false}
# Controls validation of Cassandra server hostname
ssl-hostname-validation: ${CASSANDRA_SSL_HOSTNAME_VALIDATION:true}
elasticsearch:
# host is left unset intentionally, to defer the decision
hosts: ${ES_HOSTS:}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,10 @@ abstract class BaseITZipkinEureka {
this.serviceUrl = serviceUrl;
}

@BeforeEach void awaitRegistration() {
@Test @Order(1) void registersInEureka() throws IOException {
// The zipkin server may start before Eureka processes the registration
await().until(this::getEurekaZipkinAppAsString, (s) -> true);
}

@Test @Order(1) void registersInEureka() throws IOException {
String json = getEurekaZipkinAppAsString();

// Make sure the health status is OK
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2023 The OpenZipkin Authors
* Copyright 2015-2024 The OpenZipkin Authors
*
* 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
Expand Down Expand Up @@ -124,4 +124,30 @@ class ZipkinCassandraStorageAutoConfigurationTest {
assertThat(context.getBean(CassandraStorage.class).autocompleteCardinality)
.isEqualTo(5000);
}

@Test void useSsl() {
TestPropertyValues.of(
"zipkin.storage.type:cassandra3",
"zipkin.storage.cassandra3.use-ssl:true")
.applyTo(context);
Access.registerCassandra3(context);
context.refresh();

assertThat(context.getBean(CassandraStorage.class).useSsl).isTrue();
assertThat(context.getBean(CassandraStorage.class).sslHostnameValidation).isTrue();
}

@Test void sslHostnameValidation_canSetToFalse() {
TestPropertyValues.of(
"zipkin.storage.type:cassandra3",
"zipkin.storage.cassandra3.use-ssl:true",
"zipkin.storage.cassandra3.ssl-hostname-validation:false"
)
.applyTo(context);
Access.registerCassandra3(context);
context.refresh();

assertThat(context.getBean(CassandraStorage.class).useSsl).isTrue();
assertThat(context.getBean(CassandraStorage.class).sslHostnameValidation).isFalse();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2023 The OpenZipkin Authors
* Copyright 2015-2024 The OpenZipkin Authors
*
* 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
Expand Down Expand Up @@ -93,7 +93,8 @@ public Builder sessionFactory(SessionFactory sessionFactory) {
}
return new CassandraStorage(strictTraceId, searchEnabled, autocompleteKeys, autocompleteTtl,
autocompleteCardinality, contactPoints, localDc, poolingOptions(), authProvider, useSsl,
sessionFactory, keyspace, ensureSchema, maxTraceCols, indexFetchMultiplier);
sslHostnameValidation, sessionFactory, keyspace, ensureSchema, maxTraceCols,
indexFetchMultiplier);
}
}

Expand All @@ -105,6 +106,7 @@ autocompleteCardinality, contactPoints, localDc, poolingOptions(), authProvider,
final Map<DriverOption, Integer> poolingOptions;
@Nullable final AuthProvider authProvider;
final boolean useSsl;
final boolean sslHostnameValidation;
final String keyspace;
final boolean ensureSchema;

Expand All @@ -115,8 +117,8 @@ autocompleteCardinality, contactPoints, localDc, poolingOptions(), authProvider,
CassandraStorage(boolean strictTraceId, boolean searchEnabled, Set<String> autocompleteKeys,
int autocompleteTtl, int autocompleteCardinality, String contactPoints, String localDc,
Map<DriverOption, Integer> poolingOptions, AuthProvider authProvider, boolean useSsl,
SessionFactory sessionFactory, String keyspace, boolean ensureSchema, int maxTraceCols,
int indexFetchMultiplier) {
boolean sslHostnameValidation, SessionFactory sessionFactory, String keyspace,
boolean ensureSchema, int maxTraceCols, int indexFetchMultiplier) {
// Assign generic configuration for all storage components
this.strictTraceId = strictTraceId;
this.searchEnabled = searchEnabled;
Expand All @@ -130,6 +132,7 @@ autocompleteCardinality, contactPoints, localDc, poolingOptions(), authProvider,
this.poolingOptions = poolingOptions;
this.authProvider = authProvider;
this.useSsl = useSsl;
this.sslHostnameValidation = sslHostnameValidation;
this.ensureSchema = ensureSchema;
this.keyspace = keyspace;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2023 The OpenZipkin Authors
* Copyright 2015-2024 The OpenZipkin Authors
*
* 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
Expand Down Expand Up @@ -64,7 +64,8 @@ static CqlSession buildSession(CassandraStorage cassandra) {
cassandra.localDc,
cassandra.poolingOptions,
cassandra.authProvider,
cassandra.useSsl
cassandra.useSsl,
cassandra.sslHostnameValidation
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 The OpenZipkin Authors
* Copyright 2015-2024 The OpenZipkin Authors
*
* 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
Expand Down Expand Up @@ -41,6 +41,7 @@ public abstract class CassandraStorageBuilder<B extends CassandraStorageBuilder<
protected String localDc = "datacenter1";
@Nullable protected String username, password;
protected boolean useSsl = false;
protected boolean sslHostnameValidation = true;

protected String keyspace;
protected boolean ensureSchema = true;
Expand Down Expand Up @@ -143,6 +144,12 @@ public B useSsl(boolean useSsl) {
return (B) this;
}

/** Controls validation of Cassandra server hostname. Defaults to true. */
public B sslHostnameValidation(boolean sslHostnameValidation) {
this.sslHostnameValidation = sslHostnameValidation;
return (B) this;
}

/** Keyspace to store span and index data. Defaults to "zipkin3" */
public B keyspace(String keyspace) {
if (keyspace == null) throw new NullPointerException("keyspace == null");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2023 The OpenZipkin Authors
* Copyright 2015-2024 The OpenZipkin Authors
*
* 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
Expand Down Expand Up @@ -38,6 +38,7 @@
import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.REQUEST_TRACKER_CLASS;
import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.REQUEST_WARN_IF_SET_KEYSPACE;
import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.SSL_ENGINE_FACTORY_CLASS;
import static com.datastax.oss.driver.api.core.config.DefaultDriverOption.SSL_HOSTNAME_VALIDATION;

public final class SessionBuilder {
/** Returns a connected session. Closes the cluster if any exception occurred. */
Expand All @@ -46,7 +47,8 @@ public static CqlSession buildSession(
String localDc,
Map<DriverOption, Integer> poolingOptions,
@Nullable AuthProvider authProvider,
boolean useSsl
boolean useSsl,
boolean sslHostnameValidation
) {
// Some options aren't supported by builder methods. In these cases, we use driver config
// See https://groups.google.com/a/lists.datastax.com/forum/#!topic/java-driver-user/Z8HrCDX47Q0
Expand Down Expand Up @@ -76,7 +78,10 @@ public static CqlSession buildSession(
// All Zipkin CQL writes are idempotent
config = config.withBoolean(REQUEST_DEFAULT_IDEMPOTENCE, true);

if (useSsl) config = config.withClass(SSL_ENGINE_FACTORY_CLASS, DefaultSslEngineFactory.class);
if (useSsl) {
config = config.withClass(SSL_ENGINE_FACTORY_CLASS, DefaultSslEngineFactory.class);
config = config.withBoolean(SSL_HOSTNAME_VALIDATION, sslHostnameValidation);
}

// Log categories can enable query logging
Logger requestLogger = LoggerFactory.getLogger(SessionBuilder.class);
Expand Down

0 comments on commit 899170c

Please sign in to comment.