Skip to content

Commit d264efa

Browse files
authored
Support for SSL Configuration within JerseyTest (#4573)
* Added ssl configuration support for JerseyTest Signed-off-by: Hakan Altindag <[email protected]>
1 parent 9edb3d4 commit d264efa

File tree

11 files changed

+550
-6
lines changed

11 files changed

+550
-6
lines changed

test-framework/core/src/main/java/org/glassfish/jersey/test/DeploymentContext.java

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -16,10 +16,14 @@
1616

1717
package org.glassfish.jersey.test;
1818

19+
import javax.net.ssl.SSLContext;
20+
import javax.net.ssl.SSLParameters;
1921
import javax.ws.rs.core.Application;
2022

2123
import org.glassfish.jersey.server.ResourceConfig;
2224

25+
import java.util.Optional;
26+
2327
/**
2428
* Basic application deployment context.
2529
* <p>
@@ -122,6 +126,8 @@ public static class Builder {
122126

123127
private final ResourceConfig resourceConfig;
124128
private String contextPath = DEFAULT_CONTEXT_PATH;
129+
private SSLContext sslContext;
130+
private SSLParameters sslParameters;
125131

126132
/**
127133
* 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) {
175181
return this;
176182
}
177183

184+
/**
185+
* Set the application ssl properties.
186+
*
187+
* @param sslContext application ssl context.
188+
* @param sslParameters application ssl parameters
189+
* @return this application deployment context builder.
190+
*
191+
* @throws NullPointerException if {@code sslContext} is {@code null}.
192+
*/
193+
public Builder ssl(final SSLContext sslContext, SSLParameters sslParameters) {
194+
if (sslContext == null && sslParameters == null) {
195+
throw new NullPointerException("The sslContext and sslParameters must not be null");
196+
}
197+
this.sslContext = sslContext;
198+
this.sslParameters = sslParameters;
199+
return this;
200+
}
201+
178202
/**
179203
* Build a new application deployment context configured by the current state of this
180204
* application deployment context builder.
@@ -201,6 +225,8 @@ protected void reset() {
201225

202226
private final ResourceConfig resourceConfig;
203227
private final String contextPath;
228+
private final SSLContext sslContext;
229+
private final SSLParameters sslParameters;
204230

205231
/**
206232
* Create new application deployment context.
@@ -210,6 +236,8 @@ protected void reset() {
210236
protected DeploymentContext(final Builder b) {
211237
this.contextPath = b.contextPath;
212238
this.resourceConfig = b.resourceConfig;
239+
this.sslContext = b.sslContext;
240+
this.sslParameters = b.sslParameters;
213241
}
214242

215243
/**
@@ -233,5 +261,24 @@ public ResourceConfig getResourceConfig() {
233261
public final String getContextPath() {
234262
return contextPath;
235263
}
264+
265+
/**
266+
* Get the deployed application ssl context.
267+
*
268+
* @return the deployed application ssl context.
269+
*/
270+
public Optional<SSLContext> getSslContext() {
271+
return Optional.ofNullable(sslContext);
272+
}
273+
274+
/**
275+
* Get the deployed application ssl parameters.
276+
*
277+
* @return the deployed application ssl parameters.
278+
*/
279+
public Optional<SSLParameters> getSslParameters() {
280+
return Optional.ofNullable(sslParameters);
281+
}
282+
236283
}
237284

test-framework/core/src/main/java/org/glassfish/jersey/test/JerseyTest.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -25,6 +25,7 @@
2525
import java.util.IdentityHashMap;
2626
import java.util.List;
2727
import java.util.Map;
28+
import java.util.Optional;
2829
import java.util.Properties;
2930
import java.util.Set;
3031
import java.util.concurrent.atomic.AtomicReference;
@@ -34,6 +35,8 @@
3435
import java.util.logging.LogRecord;
3536
import java.util.logging.Logger;
3637

38+
import javax.net.ssl.SSLContext;
39+
import javax.net.ssl.SSLParameters;
3740
import javax.ws.rs.client.Client;
3841
import javax.ws.rs.client.ClientBuilder;
3942
import javax.ws.rs.client.WebTarget;
@@ -417,7 +420,11 @@ protected Application configure() {
417420
* @since 2.8
418421
*/
419422
protected DeploymentContext configureDeployment() {
420-
return DeploymentContext.builder(configure()).build();
423+
DeploymentContext.Builder contextBuilder = DeploymentContext.builder(configure());
424+
if (getSslContext().isPresent() && getSslParameters().isPresent()) {
425+
contextBuilder.ssl(getSslContext().get(), getSslParameters().get());
426+
}
427+
return contextBuilder.build();
421428
}
422429

423430
/**
@@ -453,6 +460,34 @@ protected TestContainerFactory getTestContainerFactory() throws TestContainerExc
453460
return testContainerFactory;
454461
}
455462

463+
/**
464+
* Return an optional instance of {@link SSLContext} class.
465+
* <p>
466+
* <p>
467+
* This method is used only once during {@code JerseyTest} instance construction to retrieve the ssl configuration.
468+
* By default the ssl configuration is absent, to enable it please override this method and {@link JerseyTest#getSslParameters()}
469+
* </p>
470+
* </p>
471+
* @return an optional instance of {@link SSLContext} class.
472+
*/
473+
protected Optional<SSLContext> getSslContext() {
474+
return Optional.empty();
475+
}
476+
477+
/**
478+
* Return an optional instance of {@link SSLParameters} class.
479+
* <p>
480+
* <p>
481+
* This method is used only once during {@code JerseyTest} instance construction to retrieve the ssl configuration.
482+
* By default the ssl configuration is absent, to enable it please override this method and {@link JerseyTest#getSslContext()} ()}
483+
* </p>
484+
* </p>
485+
* @return an optional instance of {@link SSLContext} class.
486+
*/
487+
protected Optional<SSLParameters> getSslParameters() {
488+
return Optional.empty();
489+
}
490+
456491
private static synchronized TestContainerFactory getDefaultTestContainerFactory() {
457492

458493
if (defaultTestContainerFactoryClass == null) {

test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyTestContainerFactory.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,8 +21,10 @@
2121
import java.util.logging.Level;
2222
import java.util.logging.Logger;
2323

24+
import javax.net.ssl.SSLParameters;
2425
import javax.ws.rs.core.UriBuilder;
2526

27+
import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
2628
import org.glassfish.jersey.client.ClientConfig;
2729
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
2830
import org.glassfish.jersey.test.DeploymentContext;
@@ -56,6 +58,17 @@ private GrizzlyTestContainer(final URI baseUri, final DeploymentContext context)
5658
+ TestHelper.zeroPortToAvailablePort(baseUri));
5759
}
5860

61+
if (context.getSslContext().isPresent() && context.getSslParameters().isPresent()) {
62+
SSLParameters sslParameters = context.getSslParameters().get();
63+
this.server = GrizzlyHttpServerFactory.createHttpServer(
64+
this.baseUri, context.getResourceConfig(),
65+
true, new SSLEngineConfigurator(
66+
context.getSslContext().get(), false,
67+
sslParameters.getNeedClientAuth(), sslParameters.getWantClientAuth()),
68+
false);
69+
return;
70+
}
71+
5972
this.server = GrizzlyHttpServerFactory.createHttpServer(this.baseUri, context.getResourceConfig(), false);
6073
}
6174

test-framework/providers/grizzly2/src/main/java/org/glassfish/jersey/test/grizzly/GrizzlyWebTestContainerFactory.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -26,6 +26,7 @@
2626
import java.util.logging.Level;
2727
import java.util.logging.Logger;
2828

29+
import javax.net.ssl.SSLParameters;
2930
import javax.ws.rs.ProcessingException;
3031
import javax.ws.rs.core.UriBuilder;
3132

@@ -34,6 +35,7 @@
3435
import javax.servlet.ServletRegistration;
3536
import javax.servlet.http.HttpServlet;
3637

38+
import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
3739
import org.glassfish.jersey.client.ClientConfig;
3840
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer;
3941
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
@@ -191,8 +193,21 @@ private void instantiateGrizzlyWebServer() {
191193
}
192194
}
193195

196+
boolean secure = false;
197+
SSLEngineConfigurator sslEngineConfigurator = null;
198+
if (deploymentContext.getSslContext().isPresent() && deploymentContext.getSslParameters().isPresent()) {
199+
secure = true;
200+
SSLParameters sslParameters = deploymentContext.getSslParameters().get();
201+
sslEngineConfigurator = new SSLEngineConfigurator(
202+
deploymentContext.getSslContext().get(), false,
203+
sslParameters.getNeedClientAuth(), sslParameters.getWantClientAuth()
204+
);
205+
}
206+
194207
try {
195-
server = GrizzlyHttpServerFactory.createHttpServer(baseUri, (GrizzlyHttpContainer) null, false, null, false);
208+
server = GrizzlyHttpServerFactory.createHttpServer(
209+
baseUri, (GrizzlyHttpContainer) null,
210+
secure, sslEngineConfigurator, false);
196211
context.deploy(server);
197212
} catch (final ProcessingException ex) {
198213
throw new TestContainerException(ex);
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.jersey.test.grizzly.web.ssl;
18+
19+
import org.glassfish.jersey.server.ResourceConfig;
20+
import org.glassfish.jersey.test.JerseyTest;
21+
import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
22+
import org.glassfish.jersey.test.spi.TestContainerFactory;
23+
import org.junit.Assert;
24+
import org.junit.Rule;
25+
import org.junit.Test;
26+
import org.junit.rules.ExpectedException;
27+
28+
import javax.net.ssl.SSLContext;
29+
import javax.net.ssl.SSLParameters;
30+
import javax.ws.rs.GET;
31+
import javax.ws.rs.Path;
32+
import javax.ws.rs.ProcessingException;
33+
import javax.ws.rs.client.Client;
34+
import javax.ws.rs.client.ClientBuilder;
35+
import javax.ws.rs.client.WebTarget;
36+
import javax.ws.rs.core.Application;
37+
import javax.ws.rs.core.UriBuilder;
38+
import java.net.URI;
39+
import java.util.Optional;
40+
41+
/**
42+
* Basic GrizzlyWebTestContainerFactory unit tests.
43+
*
44+
* The test contains a server configured with SSL at https://localhost:9998/
45+
* With one way authentication the client will validate the identity of the server with
46+
* the trusted certificates within the trust store of the client. If the server is trusted
47+
* by the client the ssl handshake process will proceed or else the request will fail
48+
*
49+
* @author Hakan Altindag
50+
*/
51+
public class GrizzlyOneWaySslWebTest extends JerseyTest {
52+
53+
private SSLContext serverSslContext;
54+
private SSLParameters serverSslParameters;
55+
56+
@Rule
57+
public final ExpectedException exception = ExpectedException.none();
58+
59+
@Override
60+
protected TestContainerFactory getTestContainerFactory() {
61+
return new GrizzlyTestContainerFactory();
62+
}
63+
64+
@Path("secure")
65+
public static class TestResource {
66+
@GET
67+
public String get() {
68+
return "GET";
69+
}
70+
}
71+
72+
@Override
73+
protected Application configure() {
74+
return new ResourceConfig(TestResource.class);
75+
}
76+
77+
@Override
78+
protected URI getBaseUri() {
79+
return UriBuilder
80+
.fromUri("https://localhost")
81+
.port(getPort())
82+
.build();
83+
}
84+
85+
@Override
86+
protected Optional<SSLContext> getSslContext() {
87+
if (serverSslContext == null) {
88+
serverSslContext = SslUtils.createServerSslContext(true, false);
89+
}
90+
91+
return Optional.of(serverSslContext);
92+
}
93+
94+
@Override
95+
protected Optional<SSLParameters> getSslParameters() {
96+
if (serverSslParameters == null) {
97+
serverSslParameters = new SSLParameters();
98+
serverSslParameters.setNeedClientAuth(false);
99+
}
100+
101+
return Optional.of(serverSslParameters);
102+
}
103+
104+
@Test
105+
public void testGet() {
106+
SSLContext clientSslContext = SslUtils.createClientSslContext(false, true);
107+
108+
Client client = ClientBuilder.newBuilder()
109+
.sslContext(clientSslContext)
110+
.build();
111+
112+
WebTarget target = client.target(getBaseUri()).path("secure");
113+
114+
String s = target.request().get(String.class);
115+
Assert.assertEquals("GET", s);
116+
}
117+
118+
@Test
119+
public void testGetFailsWhenClientDoesNotTrustsServer() {
120+
SSLContext clientSslContext = SslUtils.createClientSslContext(false, false);
121+
122+
Client client = ClientBuilder.newBuilder()
123+
.sslContext(clientSslContext)
124+
.build();
125+
126+
WebTarget target = client.target(getBaseUri()).path("secure");
127+
128+
exception.expect(ProcessingException.class);
129+
130+
target.request().get(String.class);
131+
}
132+
133+
@Test
134+
public void testGetFailsWhenClientExecutesRequestWithoutHavingSslConfigured() {
135+
Client client = ClientBuilder.newClient();
136+
137+
WebTarget target = client.target(getBaseUri()).path("secure");
138+
139+
exception.expect(ProcessingException.class);
140+
141+
target.request().get(String.class);
142+
}
143+
144+
}

0 commit comments

Comments
 (0)