mirror of
https://github.com/jlengrand/helidon.git
synced 2026-03-10 08:21:17 +00:00
Updated SSL Configuration for WebServer (#1852)
* Improvements for configuration of TLS. * TLS Example for webserver. Signed-off-by: Tomas Langer <tomas.langer@oracle.com>
This commit is contained in:
@@ -398,6 +398,16 @@ public final class KeyConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass-phrase of the keystore (supported with JKS and PKCS12 keystores).
|
||||
*
|
||||
* @param keystorePassword keystore password to use, calls {@link #keystorePassphrase(char[])}
|
||||
* @return updated builder instance
|
||||
*/
|
||||
public KeystoreBuilder keystorePassphrase(String keystorePassword) {
|
||||
return keystorePassphrase(keystorePassword.toCharArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of the private key in the keystore.
|
||||
*
|
||||
@@ -446,6 +456,18 @@ public final class KeyConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass-phrase of the key in the keystore (used for private keys).
|
||||
* This is (by default) the same as keystore passphrase - only configure
|
||||
* if it differs from keystore passphrase.
|
||||
*
|
||||
* @param privateKeyPassphrase pass-phrase of the key
|
||||
* @return updated builder instance
|
||||
*/
|
||||
public KeystoreBuilder keyPassphrase(String privateKeyPassphrase) {
|
||||
return keyPassphrase(privateKeyPassphrase.toCharArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link KeyConfig} based on this builder.
|
||||
*
|
||||
@@ -654,6 +676,17 @@ public final class KeyConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passphrase for private key. If the key is encrypted (and in PEM PKCS#8 format), this passphrase will be used to
|
||||
* decrypt it.
|
||||
*
|
||||
* @param passphrase passphrase used to encrypt the private key
|
||||
* @return updated builder instance
|
||||
*/
|
||||
public PemBuilder keyPassphrase(String passphrase) {
|
||||
return keyPassphrase(passphrase.toCharArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Load certificate chain from PEM resource.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2017, 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -40,5 +40,6 @@
|
||||
<module>opentracing</module>
|
||||
<module>streaming</module>
|
||||
<module>websocket</module>
|
||||
<module>tls</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
||||
96
examples/webserver/tls/pom.xml
Normal file
96
examples/webserver/tls/pom.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
~
|
||||
~ 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
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.helidon.applications</groupId>
|
||||
<artifactId>helidon-se</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../../applications/se/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>io.helidon.examples.webserver</groupId>
|
||||
<artifactId>helidon-examples-webserver-tls</artifactId>
|
||||
<name>Helidon WebServer Examples TLS</name>
|
||||
|
||||
<description>
|
||||
Application demonstrates TLS configuration using a builder
|
||||
and config.
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<mainClass>io.helidon.webserver.examples.tls.Main</mainClass>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.helidon.webserver</groupId>
|
||||
<artifactId>helidon-webserver</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.config</groupId>
|
||||
<artifactId>helidon-config-yaml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.webclient</groupId>
|
||||
<artifactId>helidon-webclient</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.webserver</groupId>
|
||||
<artifactId>helidon-webserver-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.webclient</groupId>
|
||||
<artifactId>helidon-webclient</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-libs</id>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.helidon.webserver.examples.tls;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.logging.LogManager;
|
||||
|
||||
import io.helidon.common.configurable.Resource;
|
||||
import io.helidon.common.pki.KeyConfig;
|
||||
import io.helidon.config.Config;
|
||||
import io.helidon.webserver.Routing;
|
||||
import io.helidon.webserver.TlsConfig;
|
||||
import io.helidon.webserver.WebServer;
|
||||
|
||||
/**
|
||||
* Main class of TLS example.
|
||||
*/
|
||||
public final class Main {
|
||||
// utility class
|
||||
private Main() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the example.
|
||||
* This will start two Helidon WebServers, both protected by TLS - one configured from config, one using a builder.
|
||||
* Port of the servers will be configured from config, to be able to switch to an ephemeral port for tests.
|
||||
*
|
||||
* @param args start arguments are ignored
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
setupLogging();
|
||||
Config config = Config.create();
|
||||
startConfigBasedServer(config.get("config-based"))
|
||||
.thenAccept(ws -> {
|
||||
System.out.println("Started config based WebServer on http://localhost:" + ws.port());
|
||||
});
|
||||
startBuilderBasedServer(config.get("builder-based"))
|
||||
.thenAccept(ws -> {
|
||||
System.out.println("Started builder based WebServer on http://localhost:" + ws.port());
|
||||
});
|
||||
}
|
||||
|
||||
static CompletionStage<WebServer> startBuilderBasedServer(Config config) {
|
||||
return WebServer.builder()
|
||||
.config(config)
|
||||
.routing(routing())
|
||||
// now let's configure TLS
|
||||
.tls(TlsConfig.builder()
|
||||
.privateKey(KeyConfig.keystoreBuilder()
|
||||
.keystore(Resource.create("certificate.p12"))
|
||||
.keystorePassphrase("helidon")))
|
||||
.build()
|
||||
.start();
|
||||
}
|
||||
|
||||
static CompletionStage<WebServer> startConfigBasedServer(Config config) {
|
||||
return WebServer.builder()
|
||||
.config(config)
|
||||
.routing(routing())
|
||||
.build()
|
||||
.start();
|
||||
}
|
||||
|
||||
private static Routing routing() {
|
||||
return Routing.builder()
|
||||
.get("/", (req, res) -> res.send("Hello!"))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure logging from logging.properties file.
|
||||
*/
|
||||
private static void setupLogging() throws IOException {
|
||||
try (InputStream is = Main.class.getResourceAsStream("/logging.properties")) {
|
||||
LogManager.getLogManager().readConfiguration(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example of TLS configuration for webserver, using both {@link io.helidon.config.Config} and builder based approach.
|
||||
*/
|
||||
package io.helidon.webserver.examples.tls;
|
||||
25
examples/webserver/tls/src/main/resources/application.yaml
Normal file
25
examples/webserver/tls/src/main/resources/application.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
config-based:
|
||||
port: 8080
|
||||
ssl:
|
||||
private-key.keystore:
|
||||
resource.resource-path: "certificate.p12"
|
||||
passphrase: "helidon"
|
||||
|
||||
builder-based:
|
||||
port: 8081
|
||||
BIN
examples/webserver/tls/src/main/resources/certificate.p12
Normal file
BIN
examples/webserver/tls/src/main/resources/certificate.p12
Normal file
Binary file not shown.
20
examples/webserver/tls/src/main/resources/logging.properties
Normal file
20
examples/webserver/tls/src/main/resources/logging.properties
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
handlers=io.helidon.common.HelidonConsoleHandler
|
||||
java.util.logging.SimpleFormatter.format=[%1$tc] %4$s: %2$s - %5$s %6$s%n
|
||||
.level=INFO
|
||||
io.helidon.microprofile.server.level=INFO
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.helidon.webserver.examples.tls;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import io.helidon.config.Config;
|
||||
import io.helidon.config.ConfigSources;
|
||||
import io.helidon.webclient.Ssl;
|
||||
import io.helidon.webclient.WebClient;
|
||||
import io.helidon.webserver.WebServer;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
class MainTest {
|
||||
private static WebServer configBasedServer;
|
||||
private static WebServer builderBasedServer;
|
||||
private static WebClient configBasedClient;
|
||||
private static WebClient builderBasedClient;
|
||||
|
||||
@BeforeAll
|
||||
static void initClass() throws ExecutionException, InterruptedException {
|
||||
Config config = Config.create(ConfigSources.classpath("test-application.yaml"),
|
||||
ConfigSources.classpath("application.yaml"));
|
||||
|
||||
configBasedServer = Main.startConfigBasedServer(config.get("config-based"))
|
||||
.toCompletableFuture()
|
||||
.get();
|
||||
builderBasedServer = Main.startBuilderBasedServer(config.get("builder-based"))
|
||||
.toCompletableFuture()
|
||||
.get();
|
||||
|
||||
configBasedClient = WebClient.builder()
|
||||
.baseUri("https://localhost:" + configBasedServer.port())
|
||||
// trust all, as we use a self-signed certificate
|
||||
.ssl(Ssl.builder().trustAll(true).build())
|
||||
.build();
|
||||
|
||||
builderBasedClient = WebClient.builder()
|
||||
.baseUri("https://localhost:" + builderBasedServer.port())
|
||||
// trust all, as we use a self-signed certificate
|
||||
.ssl(Ssl.builder().trustAll(true).build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void destroyClass() {
|
||||
CompletionStage<WebServer> configBased;
|
||||
CompletionStage<WebServer> builderBased;
|
||||
|
||||
if (null == configBasedServer) {
|
||||
configBased = CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
configBased = configBasedServer.shutdown();
|
||||
}
|
||||
|
||||
if (null == builderBasedServer) {
|
||||
builderBased = CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
builderBased = builderBasedServer.shutdown();
|
||||
}
|
||||
|
||||
configBased.toCompletableFuture().join();
|
||||
builderBased.toCompletableFuture().join();
|
||||
}
|
||||
|
||||
static Stream<TestData> testDataSource() {
|
||||
return Stream.of(new TestData("Builder based", builderBasedClient),
|
||||
new TestData("Config based", configBasedClient));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("testDataSource")
|
||||
void testSsl(TestData testData) {
|
||||
String response = testData.client
|
||||
.get()
|
||||
.request(String.class)
|
||||
.await();
|
||||
|
||||
assertThat(testData.type + " SSL server response.", response, is("Hello!"));
|
||||
}
|
||||
|
||||
private static class TestData {
|
||||
private final String type;
|
||||
private final WebClient client;
|
||||
|
||||
private TestData(String type, WebClient client) {
|
||||
this.type = type;
|
||||
this.client = client;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
config-based:
|
||||
# switch to available ephemeral port for tests
|
||||
port: 0
|
||||
|
||||
builder-based:
|
||||
port: 0
|
||||
@@ -32,6 +32,7 @@ import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
@@ -219,6 +220,16 @@ public final class TlsConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure private key to use for SSL context.
|
||||
*
|
||||
* @param privateKeyConfigBuilder the required private key configuration parameter
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder privateKey(Supplier<KeyConfig> privateKeyConfigBuilder) {
|
||||
return privateKey(privateKeyConfigBuilder.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the trust key configuration to be used to validate certificates.
|
||||
*
|
||||
@@ -233,6 +244,16 @@ public final class TlsConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the trust key configuration to be used to validate certificates.
|
||||
*
|
||||
* @param trustConfigBuilder the trust configuration builder
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder trust(Supplier<KeyConfig> trustConfigBuilder) {
|
||||
return trust(trustConfigBuilder.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size of the cache used for storing SSL session objects. {@code 0} to use the
|
||||
* default value.
|
||||
|
||||
Reference in New Issue
Block a user