Wildfly – JAX RS und selbst signierte Zertifikate


In den meisten Entwicklungsumgebungen kommen selbst signierte Zertifikate zum Einsatz. Will man mit den Jackson, die Wildfly bereits bereitstellt auf solche Server zugreifen, ist einiges zu beachten. Zu Beginn sollten die Jackson Bibliotheken aus dem Wildfly in den Build eingebunden werden (grundsätzlich ist es eine gute Idee, die Bibliotheken von Wildfly auch in den Projekten zu verwenden und nicht immer neue Varianten zu deployen). Der erste Ansatz für die Umsetztung wäre es dem ClientBuilder einen entsprechenden SSLContext und einen Hostname Verifier zu übergeben, um alle Zertifikate zu akzeptieren.

try {
    SSLContext sslContext = SSLContext.getInstance(AbstractNetHelper.TLS_PROTOCOL_NAME);
    TrustManager[] trustAllCertsManager = {new TrustMangerTrustAllCerts()};
    sslContext.init(null, trustAllCertsManager, new SecureRandom());
    HostnameVerifier hostnameVerifier = null;
    if (ignoreServerNameInCertificate) {
        hostnameVerifier = new HostnameVerifierNoCheck();
    } else {
        hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
    }
    return ClientBuilder.newBuilder().hostnameVerifier(hostnameVerifier).sslContext(sslContext).newClient();
} catch (NoSuchAlgorithmException | KeyManagementException ex) {
    throw new RestException(ex);
}

Diese Implementierung ist syntaktisch korrekt führt aber nicht dazu, dass keine Prüfung der Zertifikate stattfindet. In der Dokumentation RestEasy Doku. findet sich folgendes: Network communication between the client and server is handled in RESTEasy, by default, by HttpClient (4.x) from the Apache HttpComponents project. … RESTEasy and HttpClient make reasonable default decisions so that it is possible to use the client framework without ever referencing HttpClient, but for some applications it may be necessary to drill down into the HttpClient details. ApacheHttpClient4Engine can be supplied with an instance of org.apache.http.client.HttpClient and an instance of org.apache.http.protocol.HttpContext, which can carry additional configuration details into the HttpClient layer. … Es muss also ein angepasster Apache HttpClient verwendet werden. Der HttpClient findet sich in dem Modul

org.apache.httpcomponents

Dieses Modul des WIldfly muss zur Nutzung allerdings über einen deployment-descriptor freigegeben werden. Also muss der folgende Descriptor in das Projekt aufgenommen werden (z.B. im META-INF des EAR).

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0" >
    <deployment>
        <dependencies>
            <module name="org.apache.httpcomponents" export="true" />
        </dependencies>
    </deployment>
</jboss-deployment-structure>

Im Folgenden wird ein TrustMangerTrustAllCerts angelegt (hier gibt es diverse Beispiele im Netz) und ein HostnameVerifierNoCheck (ebenfalls Beispiele im Netz). Dann werden diese dem HttpClient zugewiesen und letztendlich ein Client abgeleitet.

public Client createHttpsClientWithTimeout() {
    TrustManager[] trustAllCertsManager = {new TrustMangerTrustAllCerts()};
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, trustAllCertsManager, new SecureRandom());
    HostnameVerifier hostnameVerifier = new HostnameVerifierNoCheck();

    HttpClient httpClient = HttpClientBuilder.create()
        .setSSLContext(sslContext)
        .setSSLHostnameVerifier(new HostnameVerifierNoCheck())
        .build();
    ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
    return new ResteasyClientBuilder().httpEngine(engine).hostnameVerifier(hostnameVerifier).build();
}

Der so erzeugte Client ignoriert die Prüfung der SSL/TLS Zertifikate. Aber natürlich sollte im Betrieb außerhalb des internen Netzes und in Produktion sowieso immer ein “offiziell” signiertes Zertifikat verwendet werden. Siehe z.B. Zertifikate mit Let’s encrypt.

Du hast Fragen oder Anmerkungen? Kontakt: arndt@schoenb.de

,