From 97a2d3804e9c58917e437e7a602405c438b086e6 Mon Sep 17 00:00:00 2001 From: "Rogelio J. Baucells" Date: Fri, 29 Sep 2023 18:30:40 -0400 Subject: [PATCH 1/3] Implemented JDK HttpURLConnection based HttpClient --- aws-resources/build.gradle.kts | 2 +- .../contrib/aws/resource/Ec2Resource.java | 2 +- .../contrib/aws/resource/EcsResource.java | 6 +- .../contrib/aws/resource/EksResource.java | 8 +- .../contrib/aws/resource/JdkHttpClient.java | 119 ++++++++++++++++++ .../aws/resource/SimpleHttpClient.java | 66 +--------- .../aws/resource/SslSocketFactoryBuilder.java | 78 ++++++++++++ .../contrib/aws/resource/EcsResourceTest.java | 2 +- .../contrib/aws/resource/EksResourceTest.java | 2 +- .../aws/resource/JdkHttpClientTest.java | 110 ++++++++++++++++ 10 files changed, 320 insertions(+), 75 deletions(-) create mode 100644 aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/JdkHttpClient.java create mode 100644 aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SslSocketFactoryBuilder.java create mode 100644 aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/JdkHttpClientTest.java diff --git a/aws-resources/build.gradle.kts b/aws-resources/build.gradle.kts index 8e9471c0c..28e62d90a 100644 --- a/aws-resources/build.gradle.kts +++ b/aws-resources/build.gradle.kts @@ -16,7 +16,7 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") implementation("com.fasterxml.jackson.core:jackson-core") - implementation("com.squareup.okhttp3:okhttp") + compileOnly("com.squareup.okhttp3:okhttp") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java index 73d6517b1..3b1376ee2 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java @@ -138,7 +138,7 @@ private static String fetchHostname(URL hostnameUrl, String token) { // Generic HTTP fetch function for IMDS. private static String fetchString(String httpMethod, URL url, String token, boolean includeTtl) { - SimpleHttpClient client = new SimpleHttpClient(); + JdkHttpClient client = new JdkHttpClient(); Map headers = new HashMap<>(); if (includeTtl) { diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java index badc358f4..c85ada007 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java @@ -44,11 +44,11 @@ public static Resource get() { } private static Resource buildResource() { - return buildResource(System.getenv(), new SimpleHttpClient()); + return buildResource(System.getenv(), new JdkHttpClient()); } // Visible for testing - static Resource buildResource(Map sysEnv, SimpleHttpClient httpClient) { + static Resource buildResource(Map sysEnv, JdkHttpClient httpClient) { // Note: If V4 is set V3 is set as well, so check V4 first. String ecsMetadataUrl = sysEnv.getOrDefault(ECS_METADATA_KEY_V4, sysEnv.getOrDefault(ECS_METADATA_KEY_V3, "")); @@ -65,7 +65,7 @@ static Resource buildResource(Map sysEnv, SimpleHttpClient httpC } static void fetchMetadata( - SimpleHttpClient httpClient, String url, AttributesBuilder attrBuilders) { + JdkHttpClient httpClient, String url, AttributesBuilder attrBuilders) { String json = httpClient.fetchString("GET", url, Collections.emptyMap(), null); if (json.isEmpty()) { return; diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java index fc268098a..6327d5902 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java @@ -51,12 +51,12 @@ public static Resource get() { } private static Resource buildResource() { - return buildResource(new SimpleHttpClient(), new DockerHelper(), K8S_TOKEN_PATH, K8S_CERT_PATH); + return buildResource(new JdkHttpClient(), new DockerHelper(), K8S_TOKEN_PATH, K8S_CERT_PATH); } // Visible for testing static Resource buildResource( - SimpleHttpClient httpClient, + JdkHttpClient httpClient, DockerHelper dockerHelper, String k8sTokenPath, String k8sKeystorePath) { @@ -83,7 +83,7 @@ static Resource buildResource( } private static boolean isEks( - String k8sTokenPath, String k8sKeystorePath, SimpleHttpClient httpClient) { + String k8sTokenPath, String k8sKeystorePath, JdkHttpClient httpClient) { if (!isK8s(k8sTokenPath, k8sKeystorePath)) { logger.log(Level.FINE, "Not running on k8s."); return false; @@ -104,7 +104,7 @@ private static boolean isK8s(String k8sTokenPath, String k8sKeystorePath) { return k8sTokeyFile.exists() && k8sKeystoreFile.exists(); } - private static String getClusterName(SimpleHttpClient httpClient) { + private static String getClusterName(JdkHttpClient httpClient) { Map requestProperties = new HashMap<>(); requestProperties.put("Authorization", getK8sCredHeader()); String json = diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/JdkHttpClient.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/JdkHttpClient.java new file mode 100644 index 000000000..6d8bf98fb --- /dev/null +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/JdkHttpClient.java @@ -0,0 +1,119 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.aws.resource; + +import javax.annotation.Nullable; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A simple HTTP client based on JDK HttpURLConnection. Not meant for high throughput. + */ +final class JdkHttpClient { + + private static final Logger logger = Logger.getLogger(JdkHttpClient.class.getName()); + + private static final int TIMEOUT = 2000; + + /** Fetch a string from a remote server. */ + public String fetchString( + String httpMethod, String urlStr, Map headers, @Nullable String certPath) { + + try { + // create URL from string + URL url = new URL(urlStr); + // create connection + URLConnection connection = url.openConnection(); + // https + if (connection instanceof HttpsURLConnection) { + // cast + HttpsURLConnection httpsConnection = (HttpsURLConnection)connection; + // check CA cert path is available + if (certPath != null) { + // create trust manager + X509TrustManager trustManager = SslSocketFactoryBuilder.createTrustManager(certPath); + // socket factory + SSLSocketFactory socketFactory = SslSocketFactoryBuilder.createSocketFactory(trustManager); + if (socketFactory != null) { + // update connection + httpsConnection.setSSLSocketFactory(socketFactory); + } + } + // process request + return processRequest(httpsConnection, httpMethod, urlStr, headers); + } + // http + if (connection instanceof HttpURLConnection) { + // cast + HttpURLConnection httpConnection = (HttpURLConnection)connection; + // process request + return processRequest(httpConnection, httpMethod, urlStr, headers); + } + // not http + logger.log(Level.FINE, "JdkHttpClient only HTTP/HTTPS connections are supported."); + } catch (MalformedURLException e) { + logger.log(Level.FINE, "JdkHttpClient invalid URL.", e); + } catch (IOException e) { + logger.log(Level.FINE, "JdkHttpClient fetch string failed.", e); + } + return ""; + } + + private static String processRequest(HttpURLConnection httpConnection, String httpMethod, String urlStr, Map headers) throws IOException { + // set method + httpConnection.setRequestMethod(httpMethod); + // set headers + headers.forEach(httpConnection::setRequestProperty); + // timeouts + httpConnection.setConnectTimeout(TIMEOUT); + httpConnection.setReadTimeout(TIMEOUT); + // connect + httpConnection.connect(); + try { + // status code + int responseCode = httpConnection.getResponseCode(); + if (responseCode != 200) { + logger.log( + Level.FINE, + "Error response from " + + urlStr + + " code (" + + responseCode + + ") text " + + httpConnection.getResponseMessage()); + return ""; + } + // read response + try (InputStream inputStream = httpConnection.getInputStream()) { + // store read data in byte array + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + // read all bytes + int b; + while ((b = inputStream.read()) != -1) { + outputStream.write(b); + } + // result + return outputStream.toString("UTF-8"); + } + } + } finally { + // disconnect, no need for persistent connections + httpConnection.disconnect(); + } + } +} diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java index 12bc6e34e..0dba9d648 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java @@ -5,21 +5,13 @@ package io.opentelemetry.contrib.aws.resource; -import java.io.FileInputStream; import java.io.IOException; -import java.security.KeyStore; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; import java.time.Duration; -import java.util.Collection; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -47,9 +39,8 @@ public String fetchString( .readTimeout(TIMEOUT); if (urlStr.startsWith("https") && certPath != null) { - KeyStore keyStore = getKeystoreForTrustedCert(certPath); - X509TrustManager trustManager = buildTrustManager(keyStore); - SSLSocketFactory socketFactory = buildSslSocketFactory(trustManager); + X509TrustManager trustManager = SslSocketFactoryBuilder.createTrustManager(certPath); + SSLSocketFactory socketFactory = SslSocketFactoryBuilder.createSocketFactory(trustManager); if (socketFactory != null) { clientBuilder.sslSocketFactory(socketFactory, trustManager); } @@ -89,57 +80,4 @@ public String fetchString( return ""; } - - @Nullable - private static X509TrustManager buildTrustManager(@Nullable KeyStore keyStore) { - if (keyStore == null) { - return null; - } - try { - String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); - tmf.init(keyStore); - return (X509TrustManager) tmf.getTrustManagers()[0]; - } catch (Exception e) { - logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e); - return null; - } - } - - @Nullable - private static SSLSocketFactory buildSslSocketFactory(@Nullable TrustManager trustManager) { - if (trustManager == null) { - return null; - } - try { - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, new TrustManager[] {trustManager}, null); - return context.getSocketFactory(); - - } catch (Exception e) { - logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e); - } - return null; - } - - @Nullable - private static KeyStore getKeystoreForTrustedCert(String certPath) { - try (FileInputStream fis = new FileInputStream(certPath)) { - KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); - trustStore.load(null, null); - CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - - Collection certificates = certificateFactory.generateCertificates(fis); - - int i = 0; - for (Certificate certificate : certificates) { - trustStore.setCertificateEntry("cert_" + i, certificate); - i++; - } - return trustStore; - } catch (Exception e) { - logger.log(Level.WARNING, "Cannot load KeyStore from " + certPath); - return null; - } - } } diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SslSocketFactoryBuilder.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SslSocketFactoryBuilder.java new file mode 100644 index 000000000..4cb70dbf2 --- /dev/null +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SslSocketFactoryBuilder.java @@ -0,0 +1,78 @@ +package io.opentelemetry.contrib.aws.resource; + +import javax.annotation.Nullable; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import java.io.FileInputStream; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; + +class SslSocketFactoryBuilder { + + private static final Logger logger = Logger.getLogger(SslSocketFactoryBuilder.class.getName()); + + private SslSocketFactoryBuilder() {} + + @Nullable + private static KeyStore getKeystoreForTrustedCert(String certPath) { + try (FileInputStream fis = new FileInputStream(certPath)) { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + + Collection certificates = certificateFactory.generateCertificates(fis); + + int i = 0; + for (Certificate certificate : certificates) { + trustStore.setCertificateEntry("cert_" + i, certificate); + i++; + } + return trustStore; + } catch (Exception e) { + logger.log(Level.WARNING, "Cannot load KeyStore from " + certPath); + return null; + } + } + + @Nullable + static X509TrustManager createTrustManager(@Nullable String certPath) { + if (certPath == null) { + return null; + } + try { + // create keystore + KeyStore keyStore = getKeystoreForTrustedCert(certPath); + String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); + tmf.init(keyStore); + return (X509TrustManager) tmf.getTrustManagers()[0]; + } catch (Exception e) { + logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e); + return null; + } + } + + @Nullable + static SSLSocketFactory createSocketFactory(@Nullable TrustManager trustManager) { + if (trustManager == null) { + return null; + } + try { + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, new TrustManager[] {trustManager}, null); + return context.getSocketFactory(); + + } catch (Exception e) { + logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e); + } + return null; + } +} diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java index e822d88b0..7f5112bdf 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java @@ -31,7 +31,7 @@ class EcsResourceTest { private static final String ECS_METADATA_KEY_V4 = "ECS_CONTAINER_METADATA_URI_V4"; private static final String ECS_METADATA_KEY_V3 = "ECS_CONTAINER_METADATA_URI"; - @Mock private SimpleHttpClient mockHttpClient; + @Mock private JdkHttpClient mockHttpClient; @Test void testCreateAttributesV3() throws IOException { diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java index 7649836bb..ad7185e5c 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java @@ -34,7 +34,7 @@ public class EksResourceTest { @Mock private DockerHelper mockDockerHelper; - @Mock private SimpleHttpClient httpClient; + @Mock private JdkHttpClient httpClient; @Test void testEks(@TempDir File tempFolder) throws IOException { diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/JdkHttpClientTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/JdkHttpClientTest.java new file mode 100644 index 000000000..a924cc2de --- /dev/null +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/JdkHttpClientTest.java @@ -0,0 +1,110 @@ +package io.opentelemetry.contrib.aws.resource; + +import com.google.common.collect.ImmutableMap; +import com.linecorp.armeria.common.AggregatedHttpRequest; +import com.linecorp.armeria.common.HttpResponse; +import com.linecorp.armeria.server.ServerBuilder; +import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension; +import com.linecorp.armeria.testing.junit5.server.ServerExtension; +import com.linecorp.armeria.testing.junit5.server.mock.MockWebServerExtension; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.io.TempDir; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JdkHttpClientTest { + + @RegisterExtension + public static final MockWebServerExtension server = new MockWebServerExtension(); + + @Test + void testFetchString() { + server.enqueue(HttpResponse.of("expected result")); + + ImmutableMap requestPropertyMap = + ImmutableMap.of("key1", "value1", "key2", "value2"); + String urlStr = String.format("http://localhost:%s%s", server.httpPort(), "/path"); + JdkHttpClient httpClient = new JdkHttpClient(); + String result = httpClient.fetchString("GET", urlStr, requestPropertyMap, null); + + assertThat(result).isEqualTo("expected result"); + + AggregatedHttpRequest request1 = server.takeRequest().request(); + assertThat(request1.path()).isEqualTo("/path"); + assertThat(request1.headers().get("key1")).isEqualTo("value1"); + assertThat(request1.headers().get("key2")).isEqualTo("value2"); + } + + @Test + void testFailedFetchString() { + ImmutableMap requestPropertyMap = + ImmutableMap.of("key1", "value1", "key2", "value2"); + String urlStr = String.format("http://localhost:%s%s", server.httpPort(), "/path"); + JdkHttpClient httpClient = new JdkHttpClient(); + String result = httpClient.fetchString("GET", urlStr, requestPropertyMap, null); + assertThat(result).isEmpty(); + } + + static class HttpsServerTest { + @RegisterExtension + @Order(1) + public static final SelfSignedCertificateExtension certificate = new SelfSignedCertificateExtension(); + + @RegisterExtension + @Order(2) + public static ServerExtension server = + new ServerExtension() { + @Override + protected void configure(ServerBuilder sb) { + sb.tls(certificate.certificateFile(), certificate.privateKeyFile()); + + sb.service("/", (ctx, req) -> HttpResponse.of("Thanks for trusting me")); + } + }; + + @Test + void goodCert() { + JdkHttpClient httpClient = new JdkHttpClient(); + String result = + httpClient.fetchString( + "GET", + "https://localhost:" + server.httpsPort() + "/", + Collections.emptyMap(), + certificate.certificateFile().getAbsolutePath()); + assertThat(result).isEqualTo("Thanks for trusting me"); + } + + @Test + void missingCert() { + JdkHttpClient httpClient = new JdkHttpClient(); + String result = + httpClient.fetchString( + "GET", + "https://localhost:" + server.httpsPort() + "/", + Collections.emptyMap(), + "/foo/bar/bad"); + assertThat(result).isEmpty(); + } + + @Test + void badCert(@TempDir Path tempDir) throws Exception { + Path certFile = tempDir.resolve("test.crt"); + Files.write(certFile, "bad cert".getBytes(StandardCharsets.UTF_8)); + JdkHttpClient httpClient = new JdkHttpClient(); + String result = + httpClient.fetchString( + "GET", + "https://localhost:" + server.httpsPort() + "/", + Collections.emptyMap(), + certFile.toString()); + assertThat(result).isEmpty(); + } + } +} \ No newline at end of file From 3deb28ae2b3028ad39b3faf7936ac3083b45c10a Mon Sep 17 00:00:00 2001 From: "Rogelio J. Baucells" Date: Fri, 29 Sep 2023 19:09:29 -0400 Subject: [PATCH 2/3] fixed unit tests --- aws-resources/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/aws-resources/build.gradle.kts b/aws-resources/build.gradle.kts index 28e62d90a..f16878419 100644 --- a/aws-resources/build.gradle.kts +++ b/aws-resources/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { testImplementation("com.linecorp.armeria:armeria-junit5") testRuntimeOnly("org.bouncycastle:bcpkix-jdk15on") + testRuntimeOnly("com.squareup.okhttp3:okhttp") testImplementation("com.google.guava:guava") testImplementation("org.skyscreamer:jsonassert") } From 729219a27654cda48f9de797593cecfbc88f04cf Mon Sep 17 00:00:00 2001 From: "Rogelio J. Baucells" Date: Fri, 29 Sep 2023 19:16:51 -0400 Subject: [PATCH 3/3] code formatting --- .../contrib/aws/resource/EcsResource.java | 3 +- .../contrib/aws/resource/JdkHttpClient.java | 41 ++++++----- .../aws/resource/SslSocketFactoryBuilder.java | 18 +++-- .../aws/resource/JdkHttpClientTest.java | 71 ++++++++++--------- 4 files changed, 72 insertions(+), 61 deletions(-) diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java index c85ada007..b68a74e73 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java @@ -64,8 +64,7 @@ static Resource buildResource(Map sysEnv, JdkHttpClient httpClie return Resource.empty(); } - static void fetchMetadata( - JdkHttpClient httpClient, String url, AttributesBuilder attrBuilders) { + static void fetchMetadata(JdkHttpClient httpClient, String url, AttributesBuilder attrBuilders) { String json = httpClient.fetchString("GET", url, Collections.emptyMap(), null); if (json.isEmpty()) { return; diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/JdkHttpClient.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/JdkHttpClient.java index 6d8bf98fb..4cf9c5977 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/JdkHttpClient.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/JdkHttpClient.java @@ -5,11 +5,6 @@ package io.opentelemetry.contrib.aws.resource; -import javax.annotation.Nullable; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.X509TrustManager; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -20,10 +15,12 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; -/** - * A simple HTTP client based on JDK HttpURLConnection. Not meant for high throughput. - */ +/** A simple HTTP client based on JDK HttpURLConnection. Not meant for high throughput. */ final class JdkHttpClient { private static final Logger logger = Logger.getLogger(JdkHttpClient.class.getName()); @@ -42,13 +39,14 @@ public String fetchString( // https if (connection instanceof HttpsURLConnection) { // cast - HttpsURLConnection httpsConnection = (HttpsURLConnection)connection; + HttpsURLConnection httpsConnection = (HttpsURLConnection) connection; // check CA cert path is available if (certPath != null) { // create trust manager X509TrustManager trustManager = SslSocketFactoryBuilder.createTrustManager(certPath); // socket factory - SSLSocketFactory socketFactory = SslSocketFactoryBuilder.createSocketFactory(trustManager); + SSLSocketFactory socketFactory = + SslSocketFactoryBuilder.createSocketFactory(trustManager); if (socketFactory != null) { // update connection httpsConnection.setSSLSocketFactory(socketFactory); @@ -60,7 +58,7 @@ public String fetchString( // http if (connection instanceof HttpURLConnection) { // cast - HttpURLConnection httpConnection = (HttpURLConnection)connection; + HttpURLConnection httpConnection = (HttpURLConnection) connection; // process request return processRequest(httpConnection, httpMethod, urlStr, headers); } @@ -74,7 +72,12 @@ public String fetchString( return ""; } - private static String processRequest(HttpURLConnection httpConnection, String httpMethod, String urlStr, Map headers) throws IOException { + private static String processRequest( + HttpURLConnection httpConnection, + String httpMethod, + String urlStr, + Map headers) + throws IOException { // set method httpConnection.setRequestMethod(httpMethod); // set headers @@ -89,13 +92,13 @@ private static String processRequest(HttpURLConnection httpConnection, String ht int responseCode = httpConnection.getResponseCode(); if (responseCode != 200) { logger.log( - Level.FINE, - "Error response from " - + urlStr - + " code (" - + responseCode - + ") text " - + httpConnection.getResponseMessage()); + Level.FINE, + "Error response from " + + urlStr + + " code (" + + responseCode + + ") text " + + httpConnection.getResponseMessage()); return ""; } // read response diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SslSocketFactoryBuilder.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SslSocketFactoryBuilder.java index 4cb70dbf2..38596b1be 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SslSocketFactoryBuilder.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SslSocketFactoryBuilder.java @@ -1,11 +1,9 @@ -package io.opentelemetry.contrib.aws.resource; +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ -import javax.annotation.Nullable; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; +package io.opentelemetry.contrib.aws.resource; import java.io.FileInputStream; import java.security.KeyStore; @@ -14,6 +12,12 @@ import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; class SslSocketFactoryBuilder { diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/JdkHttpClientTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/JdkHttpClientTest.java index a924cc2de..561a60289 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/JdkHttpClientTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/JdkHttpClientTest.java @@ -1,5 +1,12 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.contrib.aws.resource; +import static org.assertj.core.api.Assertions.assertThat; + import com.google.common.collect.ImmutableMap; import com.linecorp.armeria.common.AggregatedHttpRequest; import com.linecorp.armeria.common.HttpResponse; @@ -7,17 +14,14 @@ import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension; import com.linecorp.armeria.testing.junit5.server.ServerExtension; import com.linecorp.armeria.testing.junit5.server.mock.MockWebServerExtension; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.junit.jupiter.api.io.TempDir; - import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; - -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.io.TempDir; public class JdkHttpClientTest { @@ -29,7 +33,7 @@ void testFetchString() { server.enqueue(HttpResponse.of("expected result")); ImmutableMap requestPropertyMap = - ImmutableMap.of("key1", "value1", "key2", "value2"); + ImmutableMap.of("key1", "value1", "key2", "value2"); String urlStr = String.format("http://localhost:%s%s", server.httpPort(), "/path"); JdkHttpClient httpClient = new JdkHttpClient(); String result = httpClient.fetchString("GET", urlStr, requestPropertyMap, null); @@ -45,7 +49,7 @@ void testFetchString() { @Test void testFailedFetchString() { ImmutableMap requestPropertyMap = - ImmutableMap.of("key1", "value1", "key2", "value2"); + ImmutableMap.of("key1", "value1", "key2", "value2"); String urlStr = String.format("http://localhost:%s%s", server.httpPort(), "/path"); JdkHttpClient httpClient = new JdkHttpClient(); String result = httpClient.fetchString("GET", urlStr, requestPropertyMap, null); @@ -55,29 +59,30 @@ void testFailedFetchString() { static class HttpsServerTest { @RegisterExtension @Order(1) - public static final SelfSignedCertificateExtension certificate = new SelfSignedCertificateExtension(); + public static final SelfSignedCertificateExtension certificate = + new SelfSignedCertificateExtension(); @RegisterExtension @Order(2) public static ServerExtension server = - new ServerExtension() { - @Override - protected void configure(ServerBuilder sb) { - sb.tls(certificate.certificateFile(), certificate.privateKeyFile()); + new ServerExtension() { + @Override + protected void configure(ServerBuilder sb) { + sb.tls(certificate.certificateFile(), certificate.privateKeyFile()); - sb.service("/", (ctx, req) -> HttpResponse.of("Thanks for trusting me")); - } - }; + sb.service("/", (ctx, req) -> HttpResponse.of("Thanks for trusting me")); + } + }; @Test void goodCert() { JdkHttpClient httpClient = new JdkHttpClient(); String result = - httpClient.fetchString( - "GET", - "https://localhost:" + server.httpsPort() + "/", - Collections.emptyMap(), - certificate.certificateFile().getAbsolutePath()); + httpClient.fetchString( + "GET", + "https://localhost:" + server.httpsPort() + "/", + Collections.emptyMap(), + certificate.certificateFile().getAbsolutePath()); assertThat(result).isEqualTo("Thanks for trusting me"); } @@ -85,11 +90,11 @@ void goodCert() { void missingCert() { JdkHttpClient httpClient = new JdkHttpClient(); String result = - httpClient.fetchString( - "GET", - "https://localhost:" + server.httpsPort() + "/", - Collections.emptyMap(), - "/foo/bar/bad"); + httpClient.fetchString( + "GET", + "https://localhost:" + server.httpsPort() + "/", + Collections.emptyMap(), + "/foo/bar/bad"); assertThat(result).isEmpty(); } @@ -99,12 +104,12 @@ void badCert(@TempDir Path tempDir) throws Exception { Files.write(certFile, "bad cert".getBytes(StandardCharsets.UTF_8)); JdkHttpClient httpClient = new JdkHttpClient(); String result = - httpClient.fetchString( - "GET", - "https://localhost:" + server.httpsPort() + "/", - Collections.emptyMap(), - certFile.toString()); + httpClient.fetchString( + "GET", + "https://localhost:" + server.httpsPort() + "/", + Collections.emptyMap(), + certFile.toString()); assertThat(result).isEmpty(); } } -} \ No newline at end of file +}