Skip to content

Commit

Permalink
TLS v1.3 Fallback for JDK bug (elastic#1149)
Browse files Browse the repository at this point in the history
Add fallback for TLS v1.3

Co-authored-by: Felix Barnsteiner <[email protected]>
  • Loading branch information
SylvainJuge and felixbarny authored Apr 23, 2020
1 parent 7d2c0aa commit 3c4f6e0
Show file tree
Hide file tree
Showing 9 changed files with 773 additions and 44 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ endif::[]
This is not a breaking change, so former
<<config-disable-instrumentations,`disable_instrumentation`>> configuration containing the `incubating` tag will still be respected - {pull}1123[#1123]
* Add a `--without-emulated-attach` option for runtime attachment to allow disabling this feature as a workaround.
* Add workaround for JDK bug JDK-8236039 with TLS 1.3 {pull}1149[#1149]
[float]
===== Bug fixes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package co.elastic.apm.agent.report;

import co.elastic.apm.agent.report.ssl.SslUtils;
import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.util.VersionUtils;
import org.slf4j.Logger;
Expand Down Expand Up @@ -121,27 +122,28 @@ private static List<URL> shuffleUrls(List<URL> serverUrls) {
return copy;
}

private static void trustAll(HttpsURLConnection connection) {
final SSLSocketFactory sf = SslUtils.getTrustAllSocketFactory();
if (sf != null) {
// using the same instances is important for TCP connection reuse
connection.setHostnameVerifier(SslUtils.getTrustAllHostnameVerifyer());
connection.setSSLSocketFactory(sf);
}
}

HttpURLConnection startRequest(String relativePath) throws IOException {
return startRequestToUrl(appendPathToCurrentUrl(relativePath));
}

@Nonnull
private HttpURLConnection startRequestToUrl(URL url) throws IOException {
final URLConnection connection = url.openConnection();
if (!reporterConfiguration.isVerifyServerCert()) {
if (connection instanceof HttpsURLConnection) {
trustAll((HttpsURLConnection) connection);

// change SSL socket factory to support both TLS fallback and disabling certificate validation
if (connection instanceof HttpsURLConnection) {
HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
boolean verifyServerCert = reporterConfiguration.isVerifyServerCert();

if (!verifyServerCert) {
httpsConnection.setHostnameVerifier(SslUtils.getTrustAllHostnameVerifyer());
}
SSLSocketFactory sslSocketFactory = SslUtils.getSSLSocketFactory(verifyServerCert);
if (sslSocketFactory != null) {
httpsConnection.setSSLSocketFactory(sslSocketFactory);
}
}

String secretToken = reporterConfiguration.getSecretToken();
String apiKey = reporterConfiguration.getApiKey();
String authHeaderValue = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,23 @@

public class ReporterFactory {

public Reporter createReporter(ConfigurationRegistry configurationRegistry, ApmServerClient apmServerClient, MetaData metaData) {
final ReporterConfiguration reporterConfiguration = configurationRegistry.getConfig(ReporterConfiguration.class);
final ReportingEventHandler reportingEventHandler = getReportingEventHandler(configurationRegistry,
reporterConfiguration, metaData, apmServerClient);
public Reporter createReporter(ConfigurationRegistry configurationRegistry,
ApmServerClient apmServerClient,
MetaData metaData) {

ReporterConfiguration reporterConfiguration = configurationRegistry.getConfig(ReporterConfiguration.class);
ReportingEventHandler reportingEventHandler = getReportingEventHandler(configurationRegistry, reporterConfiguration, metaData, apmServerClient);
return new ApmServerReporter(true, reporterConfiguration, reportingEventHandler);
}

@Nonnull
private ReportingEventHandler getReportingEventHandler(ConfigurationRegistry configurationRegistry,
ReporterConfiguration reporterConfiguration, MetaData metaData, ApmServerClient apmServerClient) {
ReporterConfiguration reporterConfiguration,
MetaData metaData,
ApmServerClient apmServerClient) {

final DslJsonSerializer payloadSerializer = new DslJsonSerializer(configurationRegistry.getConfig(StacktraceConfiguration.class), apmServerClient);
final ProcessorEventHandler processorEventHandler = ProcessorEventHandler.loadProcessors(configurationRegistry);
DslJsonSerializer payloadSerializer = new DslJsonSerializer(configurationRegistry.getConfig(StacktraceConfiguration.class), apmServerClient);
ProcessorEventHandler processorEventHandler = ProcessorEventHandler.loadProcessors(configurationRegistry);
return new IntakeV2ReportingEventHandler(reporterConfiguration, processorEventHandler, payloadSerializer, metaData, apmServerClient);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
* 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
Expand All @@ -22,7 +22,7 @@
* under the License.
* #L%
*/
package co.elastic.apm.agent.report;
package co.elastic.apm.agent.report.ssl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -39,20 +39,24 @@
import java.security.cert.X509Certificate;

// based on https://gist.github.com/mefarazath/c9b588044d6bffd26aac3c520660bf40
class SslUtils {
public class SslUtils {

private static final Logger logger = LoggerFactory.getLogger(SslUtils.class);

private static final HostnameVerifier hostnameVerifier;

@Nullable
private static final SSLSocketFactory socketFactory;
private static final SSLSocketFactory validateSocketFactory;

private static X509TrustManager trustAllTrustManager;
@Nullable
private static final SSLSocketFactory trustAllSocketFactory;

static {
trustAllTrustManager = createTrustAllTrustManager();
socketFactory = createTrustAllSocketFactory(trustAllTrustManager);
X509TrustManager trustAllTrustManager = createTrustAllTrustManager();
// default factory with certificate validation
validateSocketFactory = TLSFallbackSSLSocketFactory.wrapFactory(createSocketFactory(null));
// without certificate validation
trustAllSocketFactory = TLSFallbackSSLSocketFactory.wrapFactory(createSocketFactory(new TrustManager[]{trustAllTrustManager}));
hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
Expand All @@ -61,29 +65,27 @@ public boolean verify(String hostname, SSLSession session) {
};
}

static HostnameVerifier getTrustAllHostnameVerifyer() {
public static HostnameVerifier getTrustAllHostnameVerifyer() {
return hostnameVerifier;
}

@Nullable
static SSLSocketFactory getTrustAllSocketFactory() {
return socketFactory;
}

static X509TrustManager getTrustAllTrustManager() {
return trustAllTrustManager;
public static SSLSocketFactory getSSLSocketFactory(boolean validateCertificates) {
return validateCertificates ? validateSocketFactory : trustAllSocketFactory;
}

@Nullable
private static SSLSocketFactory createTrustAllSocketFactory(X509TrustManager trustAllTrustManager) {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{trustAllTrustManager};

return createSocketFactory(new TrustManager[]{trustAllTrustManager});
}

@Nullable
private static SSLSocketFactory createSocketFactory(TrustManager[] trustAllCerts) {
try {
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
logger.warn(e.getMessage(), e);
Expand All @@ -107,4 +109,5 @@ public X509Certificate[] getAcceptedIssuers() {
}
};
}

}
Loading

0 comments on commit 3c4f6e0

Please sign in to comment.