Skip to content

Commit dc597c6

Browse files
committed
[CALCITE-1480] Support specifying ciphersuites and algorithms for TLS
1 parent 63942a4 commit dc597c6

File tree

2 files changed

+161
-1
lines changed

2 files changed

+161
-1
lines changed

server/src/main/java/org/apache/calcite/avatica/server/HttpServer.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,9 @@ public static class Builder<T> {
526526

527527
private String keystoreType;
528528

529+
private String[] includeProtocols;
530+
private String[] includeCipherSuites;
531+
529532
private List<ServerCustomizer<T>> serverCustomizers = Collections.emptyList();
530533

531534
// The maximum size in bytes of an http header the server will read (64KB)
@@ -795,6 +798,29 @@ public Builder<T> withTLS(File keystore, String keystorePassword, File truststor
795798
return this;
796799
}
797800

801+
/**
802+
* Configures the server to use TLS for wire encryption.
803+
*
804+
* @param keystore The server's keystore
805+
* @param keystorePassword The keystore's password
806+
* @param truststore The truststore containing the key used to generate the server's key
807+
* @param truststorePassword The truststore's password
808+
* @param keyStoreType The keystore's type
809+
* @param includeProtocols Included TLS protocols, as expected by Jetty
810+
* @param includeCipherSuites Included cypher suites, as expected by Jetty
811+
* @return <code>this</code>
812+
*/
813+
public Builder<T> withTLS(File keystore, String keystorePassword, File truststore,
814+
String truststorePassword, String keyStoreType, String[] includeProtocols,
815+
String[] includeCipherSuites) {
816+
this.withTLS(keystore, keystorePassword, truststore, truststorePassword);
817+
// we don't want to force specifying a keyStoreType here, null is default
818+
this.keystoreType = keyStoreType;
819+
this.includeProtocols = includeProtocols;
820+
this.includeCipherSuites = includeCipherSuites;
821+
return this;
822+
}
823+
798824
/**
799825
* Adds customizers to configure a Server before startup.
800826
*
@@ -870,7 +896,8 @@ public HttpServer build() {
870896
maxAllowedHeaderSize);
871897
}
872898

873-
protected SslContextFactory.Server buildSSLContextFactory() {
899+
// Visible for testing
900+
public SslContextFactory.Server buildSSLContextFactory() {
874901
SslContextFactory.Server sslFactory = null;
875902
if (usingTLS) {
876903
sslFactory = new SslContextFactory.Server();
@@ -881,6 +908,12 @@ protected SslContextFactory.Server buildSSLContextFactory() {
881908
if (keystoreType != null && !keystoreType.equals(DEFAULT_KEYSTORE_TYPE)) {
882909
sslFactory.setKeyStoreType(keystoreType);
883910
}
911+
if (includeProtocols != null) {
912+
sslFactory.setIncludeProtocols(includeProtocols);
913+
}
914+
if (includeCipherSuites != null) {
915+
sslFactory.setIncludeCipherSuites(includeCipherSuites);
916+
}
884917
}
885918
return sslFactory;
886919
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.calcite.avatica;
18+
19+
import org.apache.calcite.avatica.remote.Driver.Serialization;
20+
import org.apache.calcite.avatica.server.HttpServer;
21+
import org.apache.calcite.avatica.server.HttpServer.Builder;
22+
23+
import org.eclipse.jetty.util.ssl.SslContextFactory.Server;
24+
import org.junit.BeforeClass;
25+
import org.junit.Test;
26+
27+
import java.sql.SQLException;
28+
29+
import static org.junit.Assert.assertArrayEquals;
30+
31+
/**
32+
* Simple unit tests for testing that the protocol/cipher suite parameters are properly propagated
33+
* to Jetty.
34+
*/
35+
public class TLSCipherTest extends HttpBaseTest {
36+
37+
public TLSCipherTest() {
38+
super("dummy");
39+
}
40+
41+
@BeforeClass
42+
public static void setup() throws SQLException {
43+
setupClass();
44+
}
45+
46+
@Test
47+
public void testTLSv11() {
48+
String[] protocolList = new String[] { "TLSv1.1" };
49+
50+
Builder httpServerBuilder =
51+
new HttpServer.Builder()
52+
.withPort(0)
53+
.withTLS(KEYSTORE, KEYSTORE_PASSWORD, KEYSTORE, KEYSTORE_PASSWORD, null,
54+
protocolList, null)
55+
.withHandler(localService, Serialization.PROTOBUF);
56+
57+
Server sslFactory = httpServerBuilder.buildSSLContextFactory();
58+
assertArrayEquals(protocolList, sslFactory.getIncludeProtocols());
59+
}
60+
61+
@Test
62+
public void testTLSv1112() {
63+
String[] protocolList = new String[] { "TLSv1.1", "TLSv1.2" };
64+
65+
Builder httpServerBuilder =
66+
new HttpServer.Builder()
67+
.withPort(0)
68+
.withTLS(KEYSTORE, KEYSTORE_PASSWORD, KEYSTORE, KEYSTORE_PASSWORD, null,
69+
protocolList, null)
70+
.withHandler(localService, Serialization.PROTOBUF);
71+
72+
Server sslFactory = httpServerBuilder.buildSSLContextFactory();
73+
assertArrayEquals(protocolList, sslFactory.getIncludeProtocols());
74+
}
75+
76+
@Test
77+
public void testSingleCipherSuite() {
78+
String[] cipherSuiteList = new String[] { "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" };
79+
80+
Builder httpServerBuilder =
81+
new HttpServer.Builder()
82+
.withPort(0)
83+
.withTLS(KEYSTORE, KEYSTORE_PASSWORD, KEYSTORE, KEYSTORE_PASSWORD, null,
84+
null, cipherSuiteList)
85+
.withHandler(localService, Serialization.PROTOBUF);
86+
87+
Server sslFactory = httpServerBuilder.buildSSLContextFactory();
88+
assertArrayEquals(cipherSuiteList, sslFactory.getIncludeCipherSuites());
89+
}
90+
91+
@Test
92+
public void testMultipleCipherSuites() {
93+
String[] cipherSuiteList =
94+
new String[] { "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
95+
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" };
96+
97+
Builder httpServerBuilder =
98+
new HttpServer.Builder()
99+
.withPort(0)
100+
.withTLS(KEYSTORE, KEYSTORE_PASSWORD, KEYSTORE, KEYSTORE_PASSWORD, null,
101+
null, cipherSuiteList)
102+
.withHandler(localService, Serialization.PROTOBUF);
103+
104+
Server sslFactory = httpServerBuilder.buildSSLContextFactory();
105+
assertArrayEquals(cipherSuiteList, sslFactory.getIncludeCipherSuites());
106+
}
107+
108+
@Test
109+
public void testProtocolAndCipherSuites() {
110+
String[] protocolList = new String[] { "TLSv1.2" };
111+
String[] cipherSuiteList =
112+
new String[] { "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
113+
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" };
114+
115+
Builder httpServerBuilder =
116+
new HttpServer.Builder()
117+
.withPort(0)
118+
.withTLS(KEYSTORE, KEYSTORE_PASSWORD, KEYSTORE, KEYSTORE_PASSWORD, null,
119+
protocolList, cipherSuiteList)
120+
.withHandler(localService, Serialization.PROTOBUF);
121+
122+
Server sslFactory = httpServerBuilder.buildSSLContextFactory();
123+
assertArrayEquals(protocolList, sslFactory.getIncludeProtocols());
124+
assertArrayEquals(cipherSuiteList, sslFactory.getIncludeCipherSuites());
125+
}
126+
127+
}

0 commit comments

Comments
 (0)