diff --git a/test-framework/core/src/main/java/org/glassfish/jersey/test/DeploymentContext.java b/test-framework/core/src/main/java/org/glassfish/jersey/test/DeploymentContext.java index 8f3dbbd1bd..f330090fd8 100644 --- a/test-framework/core/src/main/java/org/glassfish/jersey/test/DeploymentContext.java +++ b/test-framework/core/src/main/java/org/glassfish/jersey/test/DeploymentContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,10 +16,14 @@ package org.glassfish.jersey.test; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; import javax.ws.rs.core.Application; import org.glassfish.jersey.server.ResourceConfig; +import java.util.Optional; + /** * Basic application deployment context. *

@@ -122,6 +126,8 @@ public static class Builder { private final ResourceConfig resourceConfig; private String contextPath = DEFAULT_CONTEXT_PATH; + private SSLContext sslContext; + private SSLParameters sslParameters; /** * Create new deployment context builder instance not explicitly bound to the JAX-RS / Jersey application class. @@ -175,6 +181,24 @@ public Builder contextPath(final String contextPath) { return this; } + /** + * Set the application ssl properties. + * + * @param sslContext application ssl context. + * @param sslParameters application ssl parameters + * @return this application deployment context builder. + * + * @throws NullPointerException if {@code sslContext} is {@code null}. + */ + public Builder ssl(final SSLContext sslContext, SSLParameters sslParameters) { + if (sslContext == null && sslParameters == null) { + throw new NullPointerException("The sslContext and sslParameters must not be null"); + } + this.sslContext = sslContext; + this.sslParameters = sslParameters; + return this; + } + /** * Build a new application deployment context configured by the current state of this * application deployment context builder. @@ -201,6 +225,8 @@ protected void reset() { private final ResourceConfig resourceConfig; private final String contextPath; + private final SSLContext sslContext; + private final SSLParameters sslParameters; /** * Create new application deployment context. @@ -210,6 +236,8 @@ protected void reset() { protected DeploymentContext(final Builder b) { this.contextPath = b.contextPath; this.resourceConfig = b.resourceConfig; + this.sslContext = b.sslContext; + this.sslParameters = b.sslParameters; } /** @@ -233,5 +261,24 @@ public ResourceConfig getResourceConfig() { public final String getContextPath() { return contextPath; } + + /** + * Get the deployed application ssl context. + * + * @return the deployed application ssl context. + */ + public Optional getSslContext() { + return Optional.ofNullable(sslContext); + } + + /** + * Get the deployed application ssl parameters. + * + * @return the deployed application ssl parameters. + */ + public Optional getSslParameters() { + return Optional.ofNullable(sslParameters); + } + } diff --git a/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseyTest.java b/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseyTest.java index e6c0c74110..92ffa526c9 100644 --- a/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseyTest.java +++ b/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -25,6 +25,7 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; @@ -34,6 +35,8 @@ import java.util.logging.LogRecord; import java.util.logging.Logger; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.WebTarget; @@ -417,7 +420,11 @@ protected Application configure() { * @since 2.8 */ protected DeploymentContext configureDeployment() { - return DeploymentContext.builder(configure()).build(); + DeploymentContext.Builder contextBuilder = DeploymentContext.builder(configure()); + if (getSslContext().isPresent() && getSslParameters().isPresent()) { + contextBuilder.ssl(getSslContext().get(), getSslParameters().get()); + } + return contextBuilder.build(); } /** @@ -453,6 +460,34 @@ protected TestContainerFactory getTestContainerFactory() throws TestContainerExc return testContainerFactory; } + /** + * Return an optional instance of {@link SSLContext} class. + *

+ *

+ * This method is used only once during {@code JerseyTest} instance construction to retrieve the ssl configuration. + * By default the ssl configuration is absent, to enable it please override this method and {@link JerseyTest#getSslParameters()} + *

+ *

+ * @return an optional instance of {@link SSLContext} class. + */ + protected Optional getSslContext() { + return Optional.empty(); + } + + /** + * Return an optional instance of {@link SSLParameters} class. + *

+ *

+ * This method is used only once during {@code JerseyTest} instance construction to retrieve the ssl configuration. + * By default the ssl configuration is absent, to enable it please override this method and {@link JerseyTest#getSslContext()} ()} + *

+ *

+ * @return an optional instance of {@link SSLContext} class. + */ + protected Optional getSslParameters() { + return Optional.empty(); + } + private static synchronized TestContainerFactory getDefaultTestContainerFactory() { if (defaultTestContainerFactoryClass == null) { diff --git a/test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyTestContainerFactory.java b/test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyTestContainerFactory.java index 6dcaea036e..32bf86bced 100644 --- a/test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyTestContainerFactory.java +++ b/test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyTestContainerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -21,8 +21,10 @@ import java.util.logging.Level; import java.util.logging.Logger; +import javax.net.ssl.SSLParameters; import javax.ws.rs.core.UriBuilder; +import org.glassfish.grizzly.ssl.SSLEngineConfigurator; import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; import org.glassfish.jersey.test.DeploymentContext; @@ -56,6 +58,17 @@ private GrizzlyTestContainer(final URI baseUri, final DeploymentContext context) + TestHelper.zeroPortToAvailablePort(baseUri)); } + if (context.getSslContext().isPresent() && context.getSslParameters().isPresent()) { + SSLParameters sslParameters = context.getSslParameters().get(); + this.server = GrizzlyHttpServerFactory.createHttpServer( + this.baseUri, context.getResourceConfig(), + true, new SSLEngineConfigurator( + context.getSslContext().get(), false, + sslParameters.getNeedClientAuth(), sslParameters.getWantClientAuth()), + false); + return; + } + this.server = GrizzlyHttpServerFactory.createHttpServer(this.baseUri, context.getResourceConfig(), false); } diff --git a/test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyWebTestContainerFactory.java b/test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyWebTestContainerFactory.java index 1403f4d437..8620fa831d 100644 --- a/test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyWebTestContainerFactory.java +++ b/test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyWebTestContainerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -26,6 +26,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import javax.net.ssl.SSLParameters; import javax.ws.rs.ProcessingException; import javax.ws.rs.core.UriBuilder; @@ -34,6 +35,7 @@ import javax.servlet.ServletRegistration; import javax.servlet.http.HttpServlet; +import org.glassfish.grizzly.ssl.SSLEngineConfigurator; import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; @@ -191,8 +193,21 @@ private void instantiateGrizzlyWebServer() { } } + boolean secure = false; + SSLEngineConfigurator sslEngineConfigurator = null; + if (deploymentContext.getSslContext().isPresent() && deploymentContext.getSslParameters().isPresent()) { + secure = true; + SSLParameters sslParameters = deploymentContext.getSslParameters().get(); + sslEngineConfigurator = new SSLEngineConfigurator( + deploymentContext.getSslContext().get(), false, + sslParameters.getNeedClientAuth(), sslParameters.getWantClientAuth() + ); + } + try { - server = GrizzlyHttpServerFactory.createHttpServer(baseUri, (GrizzlyHttpContainer) null, false, null, false); + server = GrizzlyHttpServerFactory.createHttpServer( + baseUri, (GrizzlyHttpContainer) null, + secure, sslEngineConfigurator, false); context.deploy(server); } catch (final ProcessingException ex) { throw new TestContainerException(ex); diff --git a/test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/ssl/GrizzlyOneWaySslWebTest.java b/test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/ssl/GrizzlyOneWaySslWebTest.java new file mode 100644 index 0000000000..cad2b1d499 --- /dev/null +++ b/test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/ssl/GrizzlyOneWaySslWebTest.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.test.grizzly.web.ssl; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory; +import org.glassfish.jersey.test.spi.TestContainerFactory; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.ProcessingException; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.UriBuilder; +import java.net.URI; +import java.util.Optional; + +/** + * Basic GrizzlyWebTestContainerFactory unit tests. + * + * The test contains a server configured with SSL at https://localhost:9998/ + * With one way authentication the client will validate the identity of the server with + * the trusted certificates within the trust store of the client. If the server is trusted + * by the client the ssl handshake process will proceed or else the request will fail + * + * @author Hakan Altindag + */ +public class GrizzlyOneWaySslWebTest extends JerseyTest { + + private SSLContext serverSslContext; + private SSLParameters serverSslParameters; + + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Override + protected TestContainerFactory getTestContainerFactory() { + return new GrizzlyTestContainerFactory(); + } + + @Path("secure") + public static class TestResource { + @GET + public String get() { + return "GET"; + } + } + + @Override + protected Application configure() { + return new ResourceConfig(TestResource.class); + } + + @Override + protected URI getBaseUri() { + return UriBuilder + .fromUri("https://localhost") + .port(getPort()) + .build(); + } + + @Override + protected Optional getSslContext() { + if (serverSslContext == null) { + serverSslContext = SslUtils.createServerSslContext(true, false); + } + + return Optional.of(serverSslContext); + } + + @Override + protected Optional getSslParameters() { + if (serverSslParameters == null) { + serverSslParameters = new SSLParameters(); + serverSslParameters.setNeedClientAuth(false); + } + + return Optional.of(serverSslParameters); + } + + @Test + public void testGet() { + SSLContext clientSslContext = SslUtils.createClientSslContext(false, true); + + Client client = ClientBuilder.newBuilder() + .sslContext(clientSslContext) + .build(); + + WebTarget target = client.target(getBaseUri()).path("secure"); + + String s = target.request().get(String.class); + Assert.assertEquals("GET", s); + } + + @Test + public void testGetFailsWhenClientDoesNotTrustsServer() { + SSLContext clientSslContext = SslUtils.createClientSslContext(false, false); + + Client client = ClientBuilder.newBuilder() + .sslContext(clientSslContext) + .build(); + + WebTarget target = client.target(getBaseUri()).path("secure"); + + exception.expect(ProcessingException.class); + + target.request().get(String.class); + } + + @Test + public void testGetFailsWhenClientExecutesRequestWithoutHavingSslConfigured() { + Client client = ClientBuilder.newClient(); + + WebTarget target = client.target(getBaseUri()).path("secure"); + + exception.expect(ProcessingException.class); + + target.request().get(String.class); + } + +} diff --git a/test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/ssl/GrizzlyTwoWaySslWebTest.java b/test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/ssl/GrizzlyTwoWaySslWebTest.java new file mode 100644 index 0000000000..a085095b33 --- /dev/null +++ b/test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/ssl/GrizzlyTwoWaySslWebTest.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.test.grizzly.web.ssl; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory; +import org.glassfish.jersey.test.spi.TestContainerFactory; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.ProcessingException; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.UriBuilder; +import java.net.URI; +import java.util.Optional; + +/** + * Basic GrizzlyWebTestContainerFactory unit tests. + * + * The test contains a server configured with SSL at https://localhost:9998/ + * With two way authentication the client will validate the identity of the server with + * the trusted certificates within the trust store of the client. The server will also validate + * the identity of the client with the trusted certificates within the trust store of the server. + * If they trust each other the ssl handshake process will proceed or else the request will fail + * + * @author Hakan Altindag + */ +public class GrizzlyTwoWaySslWebTest extends JerseyTest { + + private SSLContext serverSslContext; + private SSLParameters serverSslParameters; + + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Override + protected TestContainerFactory getTestContainerFactory() { + return new GrizzlyTestContainerFactory(); + } + + @Path("more-secure") + public static class TestResource { + @GET + public String get() { + return "GET"; + } + } + + @Override + protected Application configure() { + return new ResourceConfig(TestResource.class); + } + + @Override + protected URI getBaseUri() { + return UriBuilder + .fromUri("https://localhost") + .port(getPort()) + .build(); + } + + @Override + protected Optional getSslContext() { + if (serverSslContext == null) { + serverSslContext = SslUtils.createServerSslContext(true, true); + } + + return Optional.of(serverSslContext); + } + + @Override + protected Optional getSslParameters() { + if (serverSslParameters == null) { + serverSslParameters = new SSLParameters(); + serverSslParameters.setNeedClientAuth(true); + } + + return Optional.of(serverSslParameters); + } + + @Test + public void testGet() { + SSLContext clientSslContext = SslUtils.createClientSslContext(true, true); + + Client client = ClientBuilder.newBuilder() + .sslContext(clientSslContext) + .build(); + + WebTarget target = client.target(getBaseUri()).path("more-secure"); + + String s = target.request().get(String.class); + Assert.assertEquals("GET", s); + } + + @Test + public void testGetFailsWhenClientDoesNotTrustsServer() { + SSLContext clientSslContext = SslUtils.createClientSslContext(true, false); + + Client client = ClientBuilder.newBuilder() + .sslContext(clientSslContext) + .build(); + + WebTarget target = client.target(getBaseUri()).path("more-secure"); + + exception.expect(ProcessingException.class); + + target.request().get(String.class); + } + + @Test + public void testGetFailsWhenClientCanNotIdentifyItselfToTheServer() { + SSLContext clientSslContext = SslUtils.createClientSslContext(false, true); + + Client client = ClientBuilder.newBuilder() + .sslContext(clientSslContext) + .build(); + + WebTarget target = client.target(getBaseUri()).path("more-secure"); + + exception.expect(ProcessingException.class); + + target.request().get(String.class); + } + + @Test + public void testGetFailsWhenClientExecutesRequestWithoutHavingSslConfigured() { + Client client = ClientBuilder.newClient(); + + WebTarget target = client.target(getBaseUri()).path("more-secure"); + + exception.expect(ProcessingException.class); + + target.request().get(String.class); + } + +} diff --git a/test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/ssl/SslUtils.java b/test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/ssl/SslUtils.java new file mode 100644 index 0000000000..91c096f68b --- /dev/null +++ b/test-framework/providers/grizzly2/src/test/java/org/glassfish/jersey/test/grizzly/web/ssl/SslUtils.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.test.grizzly.web.ssl; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import java.io.InputStream; +import java.security.KeyStore; + +/** + * Utility to easily create a SSLContext for a server or a client + * + * The utility class uses the keystore and truststore from the + * test resources to generate the KeyManagers, TrustManagers + * and the SSLContext + * + * @author Hakan Altindag + */ +public final class SslUtils { + + private static final String SERVER_IDENTITY_PATH = "server-identity.jks"; + private static final char[] SERVER_IDENTITY_PASSWORD = "secret".toCharArray(); + private static final String SERVER_TRUSTSTORE_PATH = "server-truststore.jks"; + private static final char[] SERVER_TRUSTSTORE_PASSWORD = "secret".toCharArray(); + + private static final String CLIENT_IDENTITY_PATH = "client-identity.jks"; + private static final char[] CLIENT_IDENTITY_PASSWORD = "secret".toCharArray(); + private static final String CLIENT_TRUSTSTORE_PATH = "client-truststore.jks"; + private static final char[] CLIENT_TRUSTSTORE_PASSWORD = "secret".toCharArray(); + + private static final String KEYSTORE_TYPE = "PKCS12"; + + private SslUtils() {} + + protected static SSLContext createServerSslContext(boolean includeKeyMaterial, boolean includeTrustMaterial) { + return createSslContext( + includeKeyMaterial, + includeTrustMaterial, + SERVER_IDENTITY_PATH, + SERVER_IDENTITY_PASSWORD, + SERVER_TRUSTSTORE_PATH, + SERVER_TRUSTSTORE_PASSWORD + ); + } + + protected static SSLContext createClientSslContext(boolean includeKeyMaterial, boolean includeTrustMaterial) { + return createSslContext( + includeKeyMaterial, + includeTrustMaterial, + CLIENT_IDENTITY_PATH, + CLIENT_IDENTITY_PASSWORD, + CLIENT_TRUSTSTORE_PATH, + CLIENT_TRUSTSTORE_PASSWORD + ); + } + + private static SSLContext createSslContext( + boolean includeKeyMaterial, + boolean includeTrustMaterial, + String keyStorePath, + char[] keyStorePassword, + String trustStorePath, + char[] trustStorePassword) { + + try { + KeyManager[] keyManagers = null; + TrustManager[] trustManagers = null; + + if (includeKeyMaterial) { + keyManagers = createKeyManagers(keyStorePath, keyStorePassword); + } + + if (includeTrustMaterial) { + trustManagers = createTrustManagers(trustStorePath, trustStorePassword); + } + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagers, trustManagers, null); + return sslContext; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static TrustManager[] createTrustManagers(String keyStorePath, char[] keyStorePassword) throws Exception { + KeyStore trustStore = getKeyStore(keyStorePath, keyStorePassword); + + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(trustStore); + return trustManagerFactory.getTrustManagers(); + } + + private static KeyManager[] createKeyManagers(String keyStorePath, char[] keyStorePassword) throws Exception { + KeyStore keyStore = getKeyStore(keyStorePath, keyStorePassword); + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, keyStorePassword); + return keyManagerFactory.getKeyManagers(); + } + + private static KeyStore getKeyStore(String path, char[] keyStorePassword) throws Exception { + try (InputStream inputStream = getResource(path)) { + KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE); + keyStore.load(inputStream, keyStorePassword); + return keyStore; + } + } + + private static InputStream getResource(String path) { + return SslUtils.class.getClassLoader().getResourceAsStream(path); + } + +} diff --git a/test-framework/providers/grizzly2/src/test/resources/client-identity.jks b/test-framework/providers/grizzly2/src/test/resources/client-identity.jks new file mode 100644 index 0000000000..d3922a11c1 Binary files /dev/null and b/test-framework/providers/grizzly2/src/test/resources/client-identity.jks differ diff --git a/test-framework/providers/grizzly2/src/test/resources/client-truststore.jks b/test-framework/providers/grizzly2/src/test/resources/client-truststore.jks new file mode 100644 index 0000000000..539185fda4 Binary files /dev/null and b/test-framework/providers/grizzly2/src/test/resources/client-truststore.jks differ diff --git a/test-framework/providers/grizzly2/src/test/resources/server-identity.jks b/test-framework/providers/grizzly2/src/test/resources/server-identity.jks new file mode 100644 index 0000000000..76a21aaedd Binary files /dev/null and b/test-framework/providers/grizzly2/src/test/resources/server-identity.jks differ diff --git a/test-framework/providers/grizzly2/src/test/resources/server-truststore.jks b/test-framework/providers/grizzly2/src/test/resources/server-truststore.jks new file mode 100644 index 0000000000..22285abc59 Binary files /dev/null and b/test-framework/providers/grizzly2/src/test/resources/server-truststore.jks differ