Configurar JettyTestContainer con SSL para JerseyTest
Me han encomendado la tarea de configurar pruebas de integración para el código de mi equipo. Estas pruebas requerirán realizar solicitudes HTTPS a los puntos finales REST implementados en Jersey 2.27. En mi búsqueda de cómo realizar este tipo de prueba, me encontré con este artículo de Baeldung que me indicó el marco de prueba de Jersey y los contenedores de proveedores que han implementado para este propósito. Elegí el contenedor Jetty, ya que nuestro código estaba usando una instancia de Jetty 'roll your own' para hacer todo esto. Comencé la implementación de nuestras pruebas y tuve dificultades para configurar SSL para el JettyTestContainer que serviría el resto de las solicitudes. Comencé a recibir una IllegalArgumentException que indicaba que "El esquema de URI debería ser http cuando no se usa SSL". No sé cómo proceder.
Aquí está mi clase de prueba:
public class ProjectTest extends JerseyTest {
private SSLContext sslCtx;
@Override
protected Application configure() {
ResourceConfig conf = new ResourceConfig(Sets.newHashSet(RestSuite1.class));
SslConfigurator sslConfig = SslConfigurator.newInstance()
.trustStoreFile()
.trustStorePassword()
.keyStoreFile()
.keyStorePassword()
sslCtx = sslConfig.createSSLContext();
}
@Override
public URI getBaseUri() {
return URI.create("https://localhost:1234")
}
@Override
public Client getClient() {
return ClientBuilder.newBuilder().sslContext(sslCtx).build();
}
@Test
public void test1() throws Exception {
String testString = "HelloWorld";
OurObject oo = target("/restSuite1")
.request()
.post(Entity.entity(testString, MediaType.APPLICATION_JSON), String.class);
}
}
Aquí hay un RestSuite1:
@Path("restSuite1")
@Produces("application/json")
public class RestSuite1 {
@POST
@Consumes("application/json")
@Produces("application/json")
public String doSomething(String payload) {
// Do Something
}
}
Aquí está mi pom.xml:
<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>
<groupId>com.sample</groupId>
<artifactId>my-application1</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>my war</name>
<url>http://some-url.com</url>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.27</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-jetty</artifactId>
<version>2.27</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Debo señalar que antes de intentar la configuración SSL, pude alcanzar el punto final POST / restSuite1 con éxito.
Encontré esta pregunta , pero no parece una configuración de SSL Grizzly que se usaría en un escenario JerseyTest.
Encontré esta pregunta , pero parece establecer roles de usuario y no una configuración SSL real.
Luego encontré esta pregunta , y la persona que la preguntó parece tener el mismo problema que yo, sin embargo, nadie respondió la pregunta.
¡Por favor ayuda!
Respuestas
Parece que esta opción no está disponible en JerseyTest. Creé una solicitud de extracción para agregar esta opción. Por favor, eche un vistazo aquí:https://github.com/eclipse-ee4j/jersey/pull/4573 No estoy muy seguro de qué tan rápido lo aprobarán y publicarán ...
Sé que no era la respuesta que estaba buscando ... Sin embargo, si aún desea configurar su servidor con ssl y probar su aplicación con https sin esperar hasta que se apruebe la solicitud de extracción, puede echar un vistazo a mi proyecto github que tiene un ejemplo básico de probar un servidor de jersey con grizzly sin JerseyTest: Application & IntegrationTest
=============== ACTUALIZACIÓN # 1 20-12-2020 ===============
La solicitud de extracción ha sido aprobada, fusionada y lanzada. Ahora está disponible a partir de la versión 2.33. Ahora es posible proporcionar un sslcontext con sslparameters para configurar su prueba de jersey. Una configuración de ejemplo sería:
public class SecuredJerseyTest extends JerseyTest {
@Override
protected TestContainerFactory getTestContainerFactory() {
return new GrizzlyTestContainerFactory();
}
@Path("hello")
public static class TestResource {
@GET
public String hello() {
return "hello";
}
}
@Override
protected Application configure() {
return new ResourceConfig(TestResource.class);
}
@Override
protected URI getBaseUri() {
return UriBuilder
.fromUri("https://localhost")
.port(getPort())
.build();
}
@Override
protected Optional<SSLContext> getSslContext() {
SSLContext sslContext = ... // your initialised server sslContext
return Optional.of(sslContext);
}
@Override
protected Optional<SSLParameters> getSslParameters() {
serverSslParameters = new SSLParameters();
serverSslParameters.setNeedClientAuth(false);
return Optional.of(serverSslParameters);
}
@Test
public void testHello() {
SSLContext sslContext = ... // your initialised client sslContext
Client client = ClientBuilder.newBuilder()
.sslContext(sslContext)
.build();
WebTarget target = client.target(getBaseUri()).path("hello");
String s = target.request().get(String.class);
Assert.assertEquals("hello", s);
}
}