diff --git a/docs/mp/jaxrs/02_server-configuration.adoc b/docs/mp/jaxrs/02_server-configuration.adoc index c0ebac3d8..6e856eb46 100644 --- a/docs/mp/jaxrs/02_server-configuration.adoc +++ b/docs/mp/jaxrs/02_server-configuration.adoc @@ -52,9 +52,52 @@ server.receive-buffer=256 server.timeout=30000 # Defaults to Runtime.availableProcessors() server.workers=4 -# Default is not to use SSL -ssl.private-key.keystore-resource-path=certificate.p12 -ssl.private-key.keystore-passphrase="abcd" +---- + +== Configuring TLS + +Helidon MP also supports custom TLS configuration. + +User is able to set following properties: + +* Server truststore + - Keystore with trusted certificates +* Private key and certificate + - Server certificate which will be used in TLS handshake + +[source,properties] +.META-INF/microprofile-config.properties - Server configuration +---- +#Truststore setup +server.tls.trust.keystore.resource.resource-path=server.p12 +server.tls.trust.keystore.passphrase=password +server.tls.trust.keystore.trust-store=true + +#Keystore with private key and server certificate +server.tls.private-key.keystore.resource.resource-path=server.p12 +server.tls.private-key.keystore.passphrase=password +---- + +Or the same configuration done in application.yaml file. + +[source,yaml] +.application.yaml - Server configuration +---- +server: + tls: + #Truststore setup + trust: + keystore: + passphrase: "password" + trust-store: true + resource: + resource-path: "keystore.p12" + #Keystore with private key and server certificate + private-key: + keystore: + passphrase: "password" + resource: + resource-path: "keystore.p12" ---- == Configuring additional ports diff --git a/docs/se/guides/15_migration.adoc b/docs/se/guides/15_migration.adoc index 0a5b51907..4f2f2e899 100644 --- a/docs/se/guides/15_migration.adoc +++ b/docs/se/guides/15_migration.adoc @@ -203,7 +203,7 @@ Configuration has been updated to use the new `Resource` approach: == WebServer Configuration === SSL/TLS -There is a new class `io.helidon.webserver.TlsConfig` that can be used +There is a new class `io.helidon.webserver.WebServerTls` that can be used to configure TLS for a WebServer socket. Class `io.helidon.webserver.SSLContextBuilder` has been deprecated and will be removed. @@ -211,7 +211,7 @@ be removed. The class uses a `Builder` pattern: [source,java] ---- -TlsConfig.builder() +WebServerTls.builder() .privateKey(KeyConfig.keystoreBuilder() .keystore(Resource.create("certificate.p12")) .keystorePassphrase("helidon") @@ -223,7 +223,7 @@ including the `WebServer.Builder` itself: [source,java] ---- WebServer.builder(routing()) - .tls(tlsConfig) + .tls(webServerTls) .build(); ---- @@ -291,6 +291,6 @@ WebServer.builder() - `io.helidon.webserver.Routing.createServer(ServerConfiguration)` - please use `WebServer.builder()` - `io.helidon.webserver.Routing.createServer()` - please use `WebServer.builder()` - `io.helidon.webserver.SocketConfiguration.DEFAULT` - use a builder to create a named configuration -- `io.helidon.webserver.SocketConfiguration.Builder.ssl(SSLContext) - use `TlsConfig` instead -- `io.helidon.webserver.SocketConfiguration.Builder.enabledSSlProtocols(String...) - use `TlsConfig` instead +- `io.helidon.webserver.SocketConfiguration.Builder.ssl(SSLContext) - use `WebServerTls` instead +- `io.helidon.webserver.SocketConfiguration.Builder.enabledSSlProtocols(String...) - use `WebServerTls` instead diff --git a/docs/se/webclient/02_tls-configuration.adoc b/docs/se/webclient/02_tls-configuration.adoc new file mode 100644 index 000000000..a59f31a02 --- /dev/null +++ b/docs/se/webclient/02_tls-configuration.adoc @@ -0,0 +1,116 @@ +/////////////////////////////////////////////////////////////////////////////// + + 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. + +/////////////////////////////////////////////////////////////////////////////// + +:h1Prefix: SE +:javadoc-base-url-api: {javadoc-base-url}io.helidon.webclient/io/helidon/webclient +:description: Helidon WebClient TLS configuration +:keywords: helidon, se, rest, httpclient, webclient, reactive, tls + += WebClient TLS configuration + +Configure TLS either programmatically or by the Helidon configuration framework. + +== Configuring TLS in your code + +The one way to configure TLS in WebClient is in your application code. + +[source,java] +---- +KeyConfig keyConfig = KeyConfig.keystoreBuilder() + //Whether this keystore is also trust store + .trustStore() + //Keystore location/name + .keystore(Resource.create("client.p12")) + //Password to the keystore + .keystorePassphrase("password") + .build(); + +WebClient.builder() + .tls(WebClientTls.builder() + .certificateTrustStore(keyConfig) + .clientKeyStore(keyConfig) + .build()) + .build(); +---- + +== Configuring TLS in the config file + +It is also possible to configure TLS via the config file. + +[source,yaml] +.WebClient TLS configuration file `application.yaml` +---- +webclient: + tls: + #Server part defines settings for server certificate validation and truststore + server: + keystore: + passphrase: "password" + trust-store: true + resource: + resource-path: "keystore.p12" + #Client part defines access to the keystore with client private key or certificate + client: + keystore: + passphrase: "password" + resource: + resource-path: "keystore.p12" +---- +Then, in your application code, load the configuration from that file. + +[source,java] +.WebClient initialization using the `application.yaml` file located on the classpath +---- +Config config = Config.create(); +WebClient webClient = WebClient.create(config.get("webclient")); +---- +Or you can only create WebClientTls instance based on the config file. + +[source,java] +.WebClientTls instance based on `application.yaml` file located on the classpath +---- +Config config = Config.create(); +WebClientTls.builder() + .config(config.get("webclient.tls")) + .build(); +---- + +== Configuration options + +See all configuration options +link:{javadoc-base-url-api}/WebClientTls.html[here]. + +Available server certificate configuration options: + +[cols="^2s,<2,<2,<6"] +|=== +|Configuration key |Default value ^|Java type ^|Description + +|`disable-hostname-verification` |false |boolean |Whether hostname verification should be performed +|`trust-all` |false |boolean |Whether all of the server certificates should be trusted +|`keystore` |{nbsp} |Object |Keystore configuration, please follow the example above +|=== + +Available client configuration options: + +[cols="^2s,<2,<2,<6"] +|=== +|Configuration key |Default value ^|Java type ^|Description + +|`keystore` |{nbsp} |Object |Keystore configuration, please follow the example above +|=== \ No newline at end of file diff --git a/docs/se/webserver/02_configuration.adoc b/docs/se/webserver/02_configuration.adoc index 9149eab64..4cd7d1f6b 100644 --- a/docs/se/webserver/02_configuration.adoc +++ b/docs/se/webserver/02_configuration.adoc @@ -86,5 +86,5 @@ Available socket configuration options: |`max-chunk-size` | `8192` |int |Maximal size of a chunk to read from incoming requests |`validate-headers` |`true` |boolean |Whether to validate header names, if they contain illegal characters. |`initial-buffer-size` |`128` |int |Initial size of buffer used to parse HTTP line and headers -|`tls` |{nbsp} |Object |Configuration of SSL, please see our SSL example in repository +|`tls` |{nbsp} |Object |Configuration of TLS, please see our TLS example in repository |=== \ No newline at end of file diff --git a/docs/se/webserver/12_tls-configuration.adoc b/docs/se/webserver/12_tls-configuration.adoc new file mode 100644 index 000000000..6884f1231 --- /dev/null +++ b/docs/se/webserver/12_tls-configuration.adoc @@ -0,0 +1,111 @@ +/////////////////////////////////////////////////////////////////////////////// + + 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. + +/////////////////////////////////////////////////////////////////////////////// + +:h1Prefix: SE +:javadoc-base-url-api: {javadoc-base-url}io.helidon.webserver/io/helidon/webserver +:description: Helidon WebServer TLS configuration +:keywords: helidon, reactive, reactive streams, reactive java, reactive webserver, tls + += WebServer TLS configuration + +Configure TLS either programmatically, or by the Helidon configuration framework. + +== Configuring TLS in your code + +To configure TLS in WebServer programmatically create your keystore configuration and pass it to the WebServer builder. + +[source,java] +---- +KeyConfig keyConfig = KeyConfig.keystoreBuilder() + //Whether this keystore is also trust store + .trustStore() + //Keystore location/name + .keystore(Resource.create("keystore.p12")) + //Password to the keystore + .keystorePassphrase("password") + .build(); + +WebServer.builder() + .tls(WebServerTls.builder() + .trust(keyConfig) + .privateKey(keyConfig) + .build()) + .build(); +---- + +== Configuring TLS in the config file + +It is also possible to configure TLS via the config file. + +[source,yaml] +.WebServer TLS configuration file `application.yaml` +---- +server: + tls: + #Truststore setup + trust: + keystore: + passphrase: "password" + trust-store: true + resource: + resource-path: "keystore.p12" + #Keystore with private key and server certificate + private-key: + keystore: + passphrase: "password" + resource: + resource-path: "keystore.p12" +---- +Then, in your application code, load the configuration from that file. + +[source,java] +.WebServer initialization using the `application.yaml` file located on the classpath +---- +Config config = Config.create(); +WebServer webClient = WebServer.create(routing, config.get("server")); +---- +Or you can only create WebServerTls instance based on the config file. + +[source,java] +.WebServerTls instance based on `application.yaml` file located on the classpath +---- +Config config = Config.create(); +WebServerTls.builder() + .config(config.get("server.tls")) + .build(); +---- + +== Configuration options + +See all configuration options +link:{javadoc-base-url-api}/WebServerTls.html[here]. + +Available server certificate configuration options: + +[cols="^2s,<2,<2,<6"] +|=== +|Configuration key |Default value ^|Java type ^|Description + +|`client-auth` |NONE |Enum |See link:{javadoc-base-url-api}/ClientAuthentication.html[here] for all possible values. +Whether to require client certificate authentication +|`protocols` |{nbsp} |String |TLS protocols to enable with the server socket +|`session-cache-size` |{nbsp} |int |The size of the cache used for storing SSL session objects +|`session-timeout-seconds` |{nbsp} |int |The timeout for the cached SSL session objects, in seconds +|`private-key` |{nbsp} |Object |Keystore configuration, please follow the example above +|`trust` |{nbsp} |Object |Keystore configuration, please follow the example above +|=== diff --git a/examples/microprofile/pom.xml b/examples/microprofile/pom.xml index 3ee8e3091..88527b65e 100644 --- a/examples/microprofile/pom.xml +++ b/examples/microprofile/pom.xml @@ -42,5 +42,6 @@ websocket messaging-sse cors + tls diff --git a/examples/microprofile/tls/README.md b/examples/microprofile/tls/README.md new file mode 100644 index 000000000..4ff2af2ce --- /dev/null +++ b/examples/microprofile/tls/README.md @@ -0,0 +1,16 @@ +# Helidon MP TLS Example + +This examples shows how to configure server TLS using Helidon MP. + +Note: This example uses self-signed server certificate! + +## Build and run + +```bash +mvn package +java -jar target/helidon-examples-microprofile-tls.jar +``` +## Exercise the application +```bash +curl -k -X GET https://localhost:8080 +``` diff --git a/examples/microprofile/tls/pom.xml b/examples/microprofile/tls/pom.xml new file mode 100644 index 000000000..fcfeefcfd --- /dev/null +++ b/examples/microprofile/tls/pom.xml @@ -0,0 +1,83 @@ + + + + 4.0.0 + + io.helidon.applications + helidon-mp + 2.0.2-SNAPSHOT + ../../../applications/mp/pom.xml + + + io.helidon.examples.microprofile + helidon-examples-microprofile-tls + Helidon Microprofile Examples TLS + + + Microprofile example that configures TLS + + + + + io.helidon.microprofile.bundles + helidon-microprofile + + + org.jboss + jandex + runtime + true + + + org.junit.jupiter + junit-jupiter-api + test + + + org.hamcrest + hamcrest-all + test + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + org.jboss.jandex + jandex-maven-plugin + + + make-index + + + + + + + \ No newline at end of file diff --git a/examples/microprofile/tls/src/main/java/io/helidon/microprofile/example/tls/GreetResource.java b/examples/microprofile/tls/src/main/java/io/helidon/microprofile/example/tls/GreetResource.java new file mode 100644 index 000000000..4748fabdd --- /dev/null +++ b/examples/microprofile/tls/src/main/java/io/helidon/microprofile/example/tls/GreetResource.java @@ -0,0 +1,50 @@ +/* + * 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.microprofile.example.tls; + +import javax.enterprise.context.RequestScoped; +import javax.json.JsonObject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/** + * A simple JAX-RS resource to greet you. Examples: + * + * Get default greeting message: + * curl -X GET https://localhost:8080 + * + * The message is returned as a plain text. + */ +@Path("/") +@RequestScoped +public class GreetResource { + + /** + * Return a greeting message. + * + * @return {@link JsonObject} + */ + @SuppressWarnings("checkstyle:designforextension") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String getDefaultMessage() { + return "Hello user!"; + } + +} diff --git a/examples/microprofile/tls/src/main/java/io/helidon/microprofile/example/tls/Main.java b/examples/microprofile/tls/src/main/java/io/helidon/microprofile/example/tls/Main.java new file mode 100644 index 000000000..ab9ad747c --- /dev/null +++ b/examples/microprofile/tls/src/main/java/io/helidon/microprofile/example/tls/Main.java @@ -0,0 +1,41 @@ +/* + * 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.microprofile.example.tls; + +import io.helidon.microprofile.server.Server; + +/** + * Starts the server. + */ +public class Main { + + private Main() { + } + + /** + * Main method. + * + * @param args args + */ + public static void main(String[] args) { + startServer(); + } + + static Server startServer() { + return Server.create().start(); + } + +} diff --git a/examples/microprofile/tls/src/main/java/io/helidon/microprofile/example/tls/package-info.java b/examples/microprofile/tls/src/main/java/io/helidon/microprofile/example/tls/package-info.java new file mode 100644 index 000000000..c2d678945 --- /dev/null +++ b/examples/microprofile/tls/src/main/java/io/helidon/microprofile/example/tls/package-info.java @@ -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. + */ + +/** + * Quickstart MicroProfile example. + */ +package io.helidon.microprofile.example.tls; diff --git a/examples/microprofile/tls/src/main/resources/META-INF/beans.xml b/examples/microprofile/tls/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..8b19b441d --- /dev/null +++ b/examples/microprofile/tls/src/main/resources/META-INF/beans.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/examples/microprofile/tls/src/main/resources/META-INF/microprofile-config.properties b/examples/microprofile/tls/src/main/resources/META-INF/microprofile-config.properties new file mode 100644 index 000000000..eb65e6a91 --- /dev/null +++ b/examples/microprofile/tls/src/main/resources/META-INF/microprofile-config.properties @@ -0,0 +1,28 @@ +# +# 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. +# + +# Microprofile server properties +server.port=8080 +server.host=0.0.0.0 + +#Truststore setup +server.tls.trust.keystore.resource.resource-path=server.p12 +server.tls.trust.keystore.passphrase=password +server.tls.trust.keystore.trust-store=true + +#Keystore with private key and server certificate +server.tls.private-key.keystore.resource.resource-path=server.p12 +server.tls.private-key.keystore.passphrase=password diff --git a/examples/microprofile/tls/src/main/resources/logging.properties b/examples/microprofile/tls/src/main/resources/logging.properties new file mode 100644 index 000000000..a71c681ab --- /dev/null +++ b/examples/microprofile/tls/src/main/resources/logging.properties @@ -0,0 +1,28 @@ +# +# 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 Logging Configuration File +# For more information see $JAVA_HOME/jre/lib/logging.properties + +# Send messages to the console +handlers=io.helidon.common.HelidonConsoleHandler + +# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread +java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n + +# Global logging level. Can be overridden by specific loggers +.level=INFO + diff --git a/examples/microprofile/tls/src/main/resources/server.p12 b/examples/microprofile/tls/src/main/resources/server.p12 new file mode 100644 index 000000000..ff8e4ddfc Binary files /dev/null and b/examples/microprofile/tls/src/main/resources/server.p12 differ diff --git a/examples/microprofile/tls/src/test/java/io/helidon/microprofile/example/tls/TlsTest.java b/examples/microprofile/tls/src/test/java/io/helidon/microprofile/example/tls/TlsTest.java new file mode 100644 index 000000000..3228977d0 --- /dev/null +++ b/examples/microprofile/tls/src/test/java/io/helidon/microprofile/example/tls/TlsTest.java @@ -0,0 +1,82 @@ +/* + * 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.microprofile.example.tls; + +import java.net.URI; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Response; + +import io.helidon.microprofile.server.Server; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * Test of the example. + */ +public class TlsTest { + + private static Client client; + static { + + try { + SSLContext sslcontext = SSLContext.getInstance("TLS"); + sslcontext.init(null, new TrustManager[]{new X509TrustManager() { + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} + public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } + }}, new java.security.SecureRandom()); + + client = ClientBuilder.newBuilder() + .sslContext(sslcontext) + .build(); + } catch (Exception e) { + e.printStackTrace(); + } + } + private static Server server; + + @BeforeAll + static void initClass() { + server = Main.startServer(); + server.start(); + } + + @AfterAll + static void destroyClass() { + server.stop(); + } + + @Test + public void testTls() { + URI restUri = URI.create("https://localhost:" + server.port() + "/"); + Response res = client.target(restUri).request().get(); + assertThat(res.getStatus(), is(200)); + assertThat(res.readEntity(String.class), is("Hello user!")); + } + +} diff --git a/examples/microprofile/tls/src/test/resources/META-INF/microprofile-config.properties b/examples/microprofile/tls/src/test/resources/META-INF/microprofile-config.properties new file mode 100644 index 000000000..32b20fab0 --- /dev/null +++ b/examples/microprofile/tls/src/test/resources/META-INF/microprofile-config.properties @@ -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. +# + +# Microprofile server properties +server.port=0 + +config_ordinal=500