Skip to content
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

Add an alternative keystore for Http Server #61

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ public HttpServer(HttpServerInfo httpServerInfo,
"http-server-timeout",
config.getTimeoutConcurrency(),
config.getTimeoutThreads());

// set up HTTP connector
ServerConnector httpConnector;
if (config.isHttpEnabled()) {
Expand Down Expand Up @@ -216,77 +217,20 @@ public HttpServer(HttpServerInfo httpServerInfo,
server.addConnector(httpConnector);
}

List<String> includedCipherSuites = config.getHttpsIncludedCipherSuites();
List<String> excludedCipherSuites = config.getHttpsExcludedCipherSuites();

// set up NIO-based HTTPS connector
ServerConnector httpsConnector;
// Set up NIO-based HTTPS connector.
if (config.isHttpsEnabled()) {
HttpConfiguration httpsConfiguration = new HttpConfiguration(baseHttpConfiguration);
httpsConfiguration.addCustomizer(new SecureRequestCustomizer());

SslContextFactory sslContextFactory = new SslContextFactory();
Optional<KeyStore> pemKeyStore = tryLoadPemKeyStore(config);
if (pemKeyStore.isPresent()) {
sslContextFactory.setKeyStore(pemKeyStore.get());
sslContextFactory.setKeyStorePassword("");
}
else {
sslContextFactory.setKeyStorePath(config.getKeystorePath());
sslContextFactory.setKeyStorePassword(config.getKeystorePassword());
if (config.getKeyManagerPassword() != null) {
sslContextFactory.setKeyManagerPassword(config.getKeyManagerPassword());
}
}
if (config.getTrustStorePath() != null) {
Optional<KeyStore> pemTrustStore = tryLoadPemTrustStore(config);
if (pemTrustStore.isPresent()) {
sslContextFactory.setTrustStore(pemTrustStore.get());
sslContextFactory.setTrustStorePassword("");
}
else {
sslContextFactory.setTrustStorePath(config.getTrustStorePath());
sslContextFactory.setTrustStorePassword(config.getTrustStorePassword());
}
}

sslContextFactory.setIncludeCipherSuites(includedCipherSuites.toArray(new String[0]));
sslContextFactory.setExcludeCipherSuites(excludedCipherSuites.toArray(new String[0]));
sslContextFactory.setSecureRandomAlgorithm(config.getSecureRandomAlgorithm());
sslContextFactory.setWantClientAuth(true);
sslContextFactory.setSslSessionTimeout((int) config.getSslSessionTimeout().getValue(SECONDS));
sslContextFactory.setSslSessionCacheSize(config.getSslSessionCacheSize());
SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(sslContextFactory, "http/1.1");

Integer acceptors = config.getHttpsAcceptorThreads();
Integer selectors = config.getHttpsSelectorThreads();
httpsConnector = createServerConnector(
httpServerInfo.getHttpsChannel(),
server,
null,
concurrentScheduler,
firstNonNull(acceptors, -1),
firstNonNull(selectors, -1),
sslConnectionFactory,
new HttpConnectionFactory(httpsConfiguration));
httpsConnector.setName("https");
httpsConnector.setPort(httpServerInfo.getHttpsUri().getPort());
httpsConnector.setIdleTimeout(config.getNetworkMaxIdleTime().toMillis());
httpsConnector.setHost(nodeInfo.getBindIp().getHostAddress());
httpsConnector.setAcceptQueueSize(config.getHttpAcceptQueueSize());

// track connection statistics
ConnectionStatistics connectionStats = new ConnectionStatistics();
httpsConnector.addBean(connectionStats);
this.httpsConnectionStats = new ConnectionStats(connectionStats);

if (channelListener != null) {
httpsConnector.addBean(channelListener);
}

ServerConnector httpsConnector = createHttpsConnector(config, nodeInfo, baseHttpConfiguration, concurrentScheduler,
channelListener, "https", httpServerInfo.getHttpsChannel(), false);
server.addConnector(httpsConnector);
}

// Set up NIO-based alternative HTTPS connector.
if (config.isHttpsEnabled() && config.isAlternativeHttpsEnabled()) {
ServerConnector alternativeHttpsConnector = createHttpsConnector(config, nodeInfo, baseHttpConfiguration, concurrentScheduler,
channelListener, "alternative-https", httpServerInfo.getAlternativeHttpsChannel(), true);
server.addConnector(alternativeHttpsConnector);
}

// set up NIO-based Admin connector
ServerConnector adminConnector;
if (theAdminServlet != null && config.isAdminEnabled()) {
Expand All @@ -308,8 +252,8 @@ public HttpServer(HttpServerInfo httpServerInfo,
}
sslContextFactory.setSecureRandomAlgorithm(config.getSecureRandomAlgorithm());
sslContextFactory.setWantClientAuth(true);
sslContextFactory.setIncludeCipherSuites(includedCipherSuites.toArray(new String[0]));
sslContextFactory.setExcludeCipherSuites(excludedCipherSuites.toArray(new String[0]));
sslContextFactory.setIncludeCipherSuites(config.getHttpsIncludedCipherSuites().toArray(new String[0]));
sslContextFactory.setExcludeCipherSuites(config.getHttpsExcludedCipherSuites().toArray(new String[0]));
SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(sslContextFactory, "http/1.1");
adminConnector = createServerConnector(
httpServerInfo.getAdminChannel(),
Expand Down Expand Up @@ -370,7 +314,7 @@ public HttpServer(HttpServerInfo httpServerInfo,
handlers.addHandler(gzipHandler);
}

handlers.addHandler(createServletContext(config, defaultServlet, servlets, parameters, filters, tokenManager, loginService, authorizer, "http", "https"));
handlers.addHandler(createServletContext(config, defaultServlet, servlets, parameters, filters, tokenManager, loginService, authorizer, "http", "https", "alternative-https"));

if (config.isRequestStatsEnabled()) {
RequestLogHandler statsRecorder = new RequestLogHandler();
Expand Down Expand Up @@ -502,9 +446,9 @@ private static DelimitedRequestLog createDelimitedRequestLog(HttpServerConfig co
config.isLogCompressionEnabled());
}

private static Optional<KeyStore> tryLoadPemKeyStore(HttpServerConfig config)
private static Optional<KeyStore> tryLoadPemKeyStore(String keystorePath, String keystorePassword)
{
File keyStoreFile = new File(config.getKeystorePath());
File keyStoreFile = new File(keystorePath);
try {
if (!PemReader.isPem(keyStoreFile)) {
return Optional.empty();
Expand All @@ -515,16 +459,16 @@ private static Optional<KeyStore> tryLoadPemKeyStore(HttpServerConfig config)
}

try {
return Optional.of(PemReader.loadKeyStore(keyStoreFile, keyStoreFile, Optional.ofNullable(config.getKeystorePassword())));
return Optional.of(PemReader.loadKeyStore(keyStoreFile, keyStoreFile, Optional.ofNullable(keystorePassword)));
}
catch (IOException | GeneralSecurityException e) {
throw new IllegalArgumentException("Error loading PEM key store: " + keyStoreFile, e);
}
}

private static Optional<KeyStore> tryLoadPemTrustStore(HttpServerConfig config)
private static Optional<KeyStore> tryLoadPemTrustStore(String trustStorePath)
{
File trustStoreFile = new File(config.getTrustStorePath());
File trustStoreFile = new File(trustStorePath);
try {
if (!PemReader.isPem(trustStoreFile)) {
return Optional.empty();
Expand Down Expand Up @@ -649,4 +593,105 @@ private static ServerConnector createServerConnector(
connector.open(channel);
return connector;
}

private ServerConnector createHttpsConnector(
HttpServerConfig config,
NodeInfo nodeInfo,
HttpConfiguration baseHttpConfiguration,
ConcurrentScheduler concurrentScheduler,
HttpServerChannelListener channelListener,
String httpsName,
ServerSocketChannel socketChannel,
Boolean useAlternative)
throws IOException
{
ServerConnector httpsConnector;
List<String> includedCipherSuites = config.getHttpsIncludedCipherSuites();
List<String> excludedCipherSuites = config.getHttpsExcludedCipherSuites();

HttpConfiguration httpsConfiguration = new HttpConfiguration(baseHttpConfiguration);
httpsConfiguration.addCustomizer(new SecureRequestCustomizer());

int httpsPort;
String trustStorePath;
String trustStorePassword;
String keystorePath;
String keystorePassword;

if (useAlternative) {
httpsPort = config.getAlternativeHttpsPort();
trustStorePath = config.getAlternativeTrustStorePath();
trustStorePassword = config.getAlternativeTrustStorePassword();
keystorePath = config.getAlternativeKeystorePath();
keystorePassword = config.getAlternativeKeystorePassword();
}
else {
httpsPort = config.getHttpsPort();
trustStorePath = config.getTrustStorePath();
trustStorePassword = config.getTrustStorePassword();
keystorePath = config.getKeystorePath();
keystorePassword = config.getKeystorePassword();
}

SslContextFactory sslContextFactory = new SslContextFactory();
Optional<KeyStore> pemKeyStore = tryLoadPemKeyStore(keystorePath, keystorePassword);
if (pemKeyStore.isPresent()) {
sslContextFactory.setKeyStore(pemKeyStore.get());
sslContextFactory.setKeyStorePassword("");
}
else {
sslContextFactory.setKeyStorePath(config.getKeystorePath());
sslContextFactory.setKeyStorePassword(config.getKeystorePassword());
if (config.getKeyManagerPassword() != null) {
sslContextFactory.setKeyManagerPassword(config.getKeyManagerPassword());
}
}
if (config.getTrustStorePath() != null) {
Optional<KeyStore> pemTrustStore = tryLoadPemTrustStore(trustStorePath);
if (pemTrustStore.isPresent()) {
sslContextFactory.setTrustStore(pemTrustStore.get());
sslContextFactory.setTrustStorePassword("");
}
else {
sslContextFactory.setTrustStorePath(config.getTrustStorePath());
sslContextFactory.setTrustStorePassword(trustStorePassword);
}
}

sslContextFactory.setIncludeCipherSuites(includedCipherSuites.toArray(new String[0]));
sslContextFactory.setExcludeCipherSuites(excludedCipherSuites.toArray(new String[0]));
sslContextFactory.setSecureRandomAlgorithm(config.getSecureRandomAlgorithm());
sslContextFactory.setWantClientAuth(true);
sslContextFactory.setSslSessionTimeout((int) config.getSslSessionTimeout().getValue(SECONDS));
sslContextFactory.setSslSessionCacheSize(config.getSslSessionCacheSize());
SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(sslContextFactory, "http/1.1");

Integer acceptors = config.getHttpsAcceptorThreads();
Integer selectors = config.getHttpsSelectorThreads();
httpsConnector = createServerConnector(
socketChannel,
server,
null,
concurrentScheduler,
firstNonNull(acceptors, -1),
firstNonNull(selectors, -1),
sslConnectionFactory,
new HttpConnectionFactory(httpsConfiguration));
httpsConnector.setName(httpsName);
httpsConnector.setPort(httpsPort);
httpsConnector.setIdleTimeout(config.getNetworkMaxIdleTime().toMillis());
httpsConnector.setHost(nodeInfo.getBindIp().getHostAddress());
httpsConnector.setAcceptQueueSize(config.getHttpAcceptQueueSize());

// track connection statistics
ConnectionStatistics connectionStats = new ConnectionStatistics();
httpsConnector.addBean(connectionStats);
this.httpsConnectionStats = new ConnectionStats(connectionStats);

if (channelListener != null) {
httpsConnector.addBean(channelListener);
}

return httpsConnector;
}
}
Loading