Skip to content
Permalink
Browse files
Add support for SSL and bindable address to sidecar
Patch by Dinesh Joshi; reviewed by Vinay Chella and Chris Lohfink for CASSANDRA-15030
  • Loading branch information
dineshjoshi authored and clohfink committed Feb 22, 2019
1 parent 5712fb4 commit 30019477cb1813c5ae75bb7ff5186c2f6d02aecb
Showing 13 changed files with 526 additions and 108 deletions.
@@ -49,7 +49,7 @@ sourceSets {
}
test {
resources {
srcDirs = [main.resources]
srcDirs = [main.resources, "src/test/resources"]
}
}
}
@@ -129,6 +129,8 @@ clean {

test {
useJUnitPlatform()
systemProperty "javax.net.ssl.trustStore", "$projectDir/src/test/resources/certs/ca.p12"
systemProperty "javax.net.ssl.trustStorePassword", "password"
}

// copyDist gets called on every build
@@ -7,7 +7,20 @@ cassandra:
- port: 9042

sidecar:
- host: 0.0.0.0
- port: 9043
#
# Enable SSL configuration (Disabled by default)
#
# - ssl:
# - enabled: true
# - keystore:
# - path: "path/to/keystore.p12"
# - password: password
# - truststore:
# - path: "path/to/truststore.p12"
# - password: password


healthcheck:
- poll_freq_millis: 30000
- poll_freq_millis: 30000
@@ -20,13 +20,15 @@

import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.vertx.core.http.HttpServer;
import org.apache.cassandra.sidecar.routes.HealthService;
import org.apache.cassandra.sidecar.utils.SslUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@Singleton
public class CassandraSidecarDaemon
{
private static final Logger logger = LoggerFactory.getLogger(CassandraSidecarDaemon.class);
@@ -45,9 +47,10 @@ public CassandraSidecarDaemon(HealthService healthService, HttpServer server, Co
public void start()
{
banner();
validate();
logger.info("Starting Cassandra Sidecar on port {}", config.getPort());
healthService.start();
server.listen();
server.listen(config.getPort(), config.getHost());
}

public void stop()
@@ -69,6 +72,25 @@ private void banner()
" ");
}

private void validate()
{
if (config.isSslEnabled())
{
try
{
SslUtils.validateSslOpts(config.getKeyStorePath(), config.getKeystorePassword());

if (config.getTrustStorePath() != null && config.getTruststorePassword() != null)
SslUtils.validateSslOpts(config.getTrustStorePath(), config.getTruststorePassword());
} catch (Exception e)
{
throw new RuntimeException("Invalid keystore parameters for SSL", e);
}
}

}


public static void main(String[] args)
{
CassandraSidecarDaemon app = Guice.createInjector(new MainModule())
@@ -32,24 +32,46 @@
/* Sidecar's HTTP REST API port */
private final Integer port;

/* Sidecar's listen address */
private String host;

/* Healthcheck frequency in miilis */
private final Integer healthCheckFrequencyMillis;

/* SSL related settings */
private final String keyStorePath;
private final String keyStorePassword;

private final String trustStorePath;
private final String trustStorePassword;

private final boolean isSslEnabled;

/**
* Constructor
*
* @param cassandraHost
* @param cassandraPort
* @param port
* @param healthCheckFrequencyMillis
* @param trustStorePath
* @param trustStorePassword
*/
public Configuration(String cassandraHost, Integer cassandraPort, Integer port,
Integer healthCheckFrequencyMillis)
public Configuration(String cassandraHost, Integer cassandraPort, String host, Integer port,
Integer healthCheckFrequencyMillis, String keyStorePath, String keyStorePassword,
String trustStorePath, String trustStorePassword, boolean isSslEnabled)
{
this.cassandraHost = cassandraHost;
this.cassandraPort = cassandraPort;
this.host = host;
this.port = port;
this.healthCheckFrequencyMillis = healthCheckFrequencyMillis;

this.keyStorePath = keyStorePath;
this.keyStorePassword = keyStorePassword;
this.trustStorePath = trustStorePath;
this.trustStorePassword = trustStorePassword;
this.isSslEnabled = isSslEnabled;
}

/**
@@ -72,6 +94,16 @@ public Integer getCassandraPort()
return cassandraPort;
}

/**
* Sidecar's listen address
*
* @return
*/
public String getHost()
{
return host;
}

/**
* Get the Sidecar's REST HTTP API port
*
@@ -91,4 +123,137 @@ public Integer getHealthCheckFrequencyMillis()
{
return healthCheckFrequencyMillis;
}

/**
* Get the SSL status
*
* @return
*/
public boolean isSslEnabled()
{
return isSslEnabled;
}

/**
* Get the Keystore Path
*
* @return
*/
public String getKeyStorePath()
{
return keyStorePath;
}

/**
* Get the Keystore password
*
* @return
*/
public String getKeystorePassword()
{
return keyStorePassword;
}

/**
* Get the Truststore Path
*
* @return
*/
public String getTrustStorePath()
{
return trustStorePath;
}

/**
* Get the Truststore password
*
* @return
*/
public String getTruststorePassword()
{
return trustStorePassword;
}

/**
* Configuration Builder
*/
public static class Builder
{
private String cassandraHost;
private Integer cassandraPort;
private String host;
private Integer port;
private Integer healthCheckFrequencyMillis;
private String keyStorePath;
private String keyStorePassword;
private String trustStorePath;
private String trustStorePassword;
private boolean isSslEnabled;

public Builder setCassandraHost(String host)
{
this.cassandraHost = host;
return this;
}

public Builder setCassandraPort(Integer port)
{
this.cassandraPort = port;
return this;
}

public Builder setHost(String host)
{
this.host = host;
return this;
}

public Builder setPort(Integer port)
{
this.port = port;
return this;
}

public Builder setHealthCheckFrequency(Integer freqMillis)
{
this.healthCheckFrequencyMillis = freqMillis;
return this;
}

public Builder setKeyStorePath(String path)
{
this.keyStorePath = path;
return this;
}

public Builder setKeyStorePassword(String password)
{
this.keyStorePassword = password;
return this;
}

public Builder setTrustStorePath(String path)
{
this.trustStorePath = path;
return this;
}

public Builder setTrustStorePassword(String password)
{
this.trustStorePassword = password;
return this;
}

public Builder setSslEnabled(boolean enabled)
{
this.isSslEnabled = enabled;
return this;
}

public Configuration build()
{
return new Configuration(cassandraHost, cassandraPort, host, port, healthCheckFrequencyMillis,
keyStorePath, keyStorePassword, trustStorePath, trustStorePassword, isSslEnabled);
}
}
}
@@ -25,6 +25,7 @@
import io.vertx.core.VertxOptions;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.net.JksOptions;
import io.vertx.ext.dropwizard.DropwizardMetricsOptions;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.LoggerHandler;
@@ -39,12 +40,6 @@

public class MainModule extends AbstractModule
{
@Override
protected void configure()
{
bind(CassandraSidecarDaemon.class).in(Singleton.class);
}

@Provides
@Singleton
public Vertx getVertx()
@@ -67,11 +62,26 @@ public HealthService healthService(Configuration config)

@Provides
@Singleton
public HttpServer vertxServer(Vertx vertx, Configuration config, Router router)
public HttpServer vertxServer(Vertx vertx, Router router, Configuration conf)
{
HttpServer server = vertx.createHttpServer(new HttpServerOptions()
.setPort(config.getPort())
.setLogActivity(true));
HttpServerOptions options = new HttpServerOptions().setLogActivity(true);

if (conf.isSslEnabled())
{
options.setKeyStoreOptions(new JksOptions()
.setPath(conf.getKeyStorePath())
.setPassword(conf.getKeystorePassword()))
.setSsl(conf.isSslEnabled());

if (conf.getTrustStorePath() != null && conf.getTruststorePassword() != null)
{
options.setTrustStoreOptions(new JksOptions()
.setPath(conf.getTrustStorePath())
.setPassword(conf.getTruststorePassword()));
}
}

HttpServer server = vertx.createHttpServer(options);
server.requestHandler(router);
return server;
}
@@ -102,10 +112,17 @@ public Configuration configuration() throws ConfigurationException
File propFile = new File("sidecar.yaml");
YAMLConfiguration yamlConf = confs.fileBased(YAMLConfiguration.class, propFile);

return new Configuration(
yamlConf.get(String.class, "cassandra.host"),
yamlConf.get(Integer.class, "cassandra.port"),
yamlConf.get(Integer.class, "sidecar.port"),
yamlConf.get(Integer.class, "healthcheck.poll_freq_millis"));
return new Configuration.Builder()
.setCassandraHost(yamlConf.get(String.class, "cassandra.host"))
.setCassandraPort(yamlConf.get(Integer.class, "cassandra.port"))
.setHost(yamlConf.get(String.class, "sidecar.host"))
.setPort(yamlConf.get(Integer.class, "sidecar.port"))
.setHealthCheckFrequency(yamlConf.get(Integer.class, "healthcheck.poll_freq_millis"))
.setKeyStorePath(yamlConf.get(String.class, "sidecar.ssl.keystore.path", null))
.setKeyStorePassword(yamlConf.get(String.class, "sidecar.ssl.keystore.password", null))
.setTrustStorePath(yamlConf.get(String.class, "sidecar.ssl.truststore.path", null))
.setTrustStorePassword(yamlConf.get(String.class, "sidecar.ssl.truststore.password", null))
.setSslEnabled(yamlConf.get(Boolean.class, "sidecar.ssl.enabled", false))
.build();
}
}

0 comments on commit 3001947

Please sign in to comment.