diff --git a/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml b/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
index b07da304ba766..67e2613f1df90 100755
--- a/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
+++ b/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
@@ -167,7 +167,7 @@
-
+
diff --git a/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/JREKeyStoreFactory.java b/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/JREKeyStoreFactory.java
new file mode 100644
index 0000000000000..3d99fb5143dce
--- /dev/null
+++ b/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/JREKeyStoreFactory.java
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.security.keyvault.jca.implementation;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.AccessController;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedAction;
+import java.security.cert.CertificateException;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.logging.Logger;
+import java.util.stream.Stream;
+
+import static java.util.logging.Level.WARNING;
+
+/**
+ * This class provides a JRE key store.
+ */
+public final class JREKeyStoreFactory {
+ private static final String JAVA_HOME = privilegedGetProperty("java.home", "");
+ private static final Path STORE_PATH = Paths.get(JAVA_HOME).resolve("lib").resolve("security");
+ private static final Path DEFAULT_STORE = STORE_PATH.resolve("cacerts");
+ private static final Path JSSE_DEFAULT_STORE = STORE_PATH.resolve("jssecacerts");
+ private static final String KEY_STORE_PASSWORD = privilegedGetProperty("javax.net.ssl.keyStorePassword", "changeit");
+ private static final Logger LOGGER = Logger.getLogger(JREKeyStoreFactory.class.getName());
+ private static final KeyStore JRE_KEY_STORE = getJreKeyStore();
+
+
+ private JREKeyStoreFactory() {
+
+ }
+
+ /**
+ * This method returns the instance of JRE key store
+ * @return the JRE key store.
+ */
+ public static KeyStore getDefaultKeyStore() {
+ return JRE_KEY_STORE;
+ }
+
+
+ private static KeyStore getJreKeyStore() {
+ KeyStore defaultKeyStore = null;
+ try {
+ defaultKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ loadKeyStore(defaultKeyStore);
+ } catch (KeyStoreException e) {
+ LOGGER.log(WARNING, "Unable to get the jre key store.", e);
+ }
+ return defaultKeyStore;
+ }
+
+ private static void loadKeyStore(KeyStore ks) {
+ try (InputStream inputStream = Files.newInputStream(getKeyStoreFile())) {
+ ks.load(inputStream, KEY_STORE_PASSWORD.toCharArray());
+ } catch (IOException | NoSuchAlgorithmException | CertificateException e) {
+ LOGGER.log(WARNING, "unable to load the jre key store", e);
+ }
+ }
+
+ private static Path getKeyStoreFile() {
+ return Stream.of(getConfiguredKeyStorePath(), JSSE_DEFAULT_STORE, DEFAULT_STORE)
+ .filter(Objects::nonNull)
+ .filter(Files::exists)
+ .filter(Files::isReadable)
+ .findFirst()
+ .orElse(null);
+ }
+
+ private static Path getConfiguredKeyStorePath() {
+ String configuredKeyStorePath = privilegedGetProperty("javax.net.ssl.keyStore", "");
+ return Optional.of(configuredKeyStorePath)
+ .filter(path -> !path.isEmpty())
+ .map(Paths::get)
+ .orElse(null);
+ }
+
+ private static String privilegedGetProperty(String theProp, String defaultVal) {
+ return AccessController.doPrivileged(
+ (PrivilegedAction) () -> {
+ String value = System.getProperty(theProp, "");
+ return (value.isEmpty()) ? defaultVal : value;
+ });
+ }
+}
diff --git a/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/certificates/JreCertificates.java b/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/certificates/JreCertificates.java
index b5ececb6d4a6b..240491300d2e2 100644
--- a/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/certificates/JreCertificates.java
+++ b/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/certificates/JreCertificates.java
@@ -3,28 +3,17 @@
package com.azure.security.keyvault.jca.implementation.certificates;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.AccessController;
+import com.azure.security.keyvault.jca.implementation.JREKeyStoreFactory;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivilegedAction;
import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.util.stream.Stream;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.HashMap;
import java.util.logging.Logger;
-import java.util.Objects;
-
import static java.util.logging.Level.WARNING;
/**
@@ -52,7 +41,7 @@ public final class JreCertificates implements AzureCertificates {
private final Map keys;
/**
- * Stores the singleton
+ * Stores the instance of JreCertificates.
*/
private static final JreCertificates INSTANCE = new JreCertificates();
@@ -60,7 +49,7 @@ public final class JreCertificates implements AzureCertificates {
* Private constructor
*/
private JreCertificates() {
- KeyStore jreKeyStore = JREKeyStore.getDefault();
+ KeyStore jreKeyStore = JREKeyStoreFactory.getDefaultKeyStore();
aliases = Optional.ofNullable(jreKeyStore)
.map(a -> {
try {
@@ -87,7 +76,7 @@ private JreCertificates() {
/**
*
- * @return the singleton.
+ * @return the instance of JreCertificates.
*/
public static JreCertificates getInstance() {
return INSTANCE;
@@ -113,56 +102,4 @@ public Map getCertificateKeys() {
public void deleteEntry(String alias) {
}
-
- private static class JREKeyStore {
- private static final String JAVA_HOME = privilegedGetProperty("java.home", "");
- private static final Path STORE_PATH = Paths.get(JAVA_HOME).resolve("lib").resolve("security");
- private static final Path DEFAULT_STORE = STORE_PATH.resolve("cacerts");
- private static final Path JSSE_DEFAULT_STORE = STORE_PATH.resolve("jssecacerts");
- private static final String KEY_STORE_PASSWORD = privilegedGetProperty("javax.net.ssl.keyStorePassword", "changeit");
-
- private static KeyStore getDefault() {
- KeyStore defaultKeyStore = null;
- try {
- defaultKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
- loadKeyStore(defaultKeyStore);
- } catch (KeyStoreException e) {
- LOGGER.log(WARNING, "Unable to get the jre key store.", e);
- }
- return defaultKeyStore;
- }
-
- private static void loadKeyStore(KeyStore ks) {
- try (InputStream inputStream = Files.newInputStream(getKeyStoreFile())) {
- ks.load(inputStream, KEY_STORE_PASSWORD.toCharArray());
- } catch (IOException | NoSuchAlgorithmException | CertificateException e) {
- LOGGER.log(WARNING, "unable to load the jre key store", e);
- }
- }
-
- private static Path getKeyStoreFile() {
- return Stream.of(getConfiguredKeyStorePath(), JSSE_DEFAULT_STORE, DEFAULT_STORE)
- .filter(Objects::nonNull)
- .filter(Files::exists)
- .filter(Files::isReadable)
- .findFirst()
- .orElse(null);
- }
-
- private static Path getConfiguredKeyStorePath() {
- String configuredKeyStorePath = privilegedGetProperty("javax.net.ssl.keyStore", "");
- return Optional.of(configuredKeyStorePath)
- .filter(path -> !path.isEmpty())
- .map(Paths::get)
- .orElse(null);
- }
-
- private static String privilegedGetProperty(String theProp, String defaultVal) {
- return AccessController.doPrivileged(
- (PrivilegedAction) () -> {
- String value = System.getProperty(theProp, "");
- return (value.isEmpty()) ? defaultVal : value;
- });
- }
- }
}
diff --git a/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtil.java b/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtil.java
index a53faeed4e980..2972c7b3e876b 100644
--- a/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtil.java
+++ b/sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtil.java
@@ -2,24 +2,39 @@
// Licensed under the MIT License.
package com.azure.security.keyvault.jca.implementation.utils;
+import com.azure.security.keyvault.jca.implementation.JREKeyStoreFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Optional;
+import java.util.logging.Logger;
import java.util.stream.Stream;
+import static java.util.logging.Level.WARNING;
+
/**
* The RestClient that uses the Apache HttpClient class.
*/
@@ -33,10 +48,11 @@ public final class HttpUtil {
.map(Package::getImplementationVersion)
.orElse(DEFAULT_VERSION);
public static final String USER_AGENT_VALUE = getUserAgentPrefix() + VERSION;
+ private static final Logger LOGGER = Logger.getLogger(HttpUtil.class.getName());
public static String get(String url, Map headers) {
String result = null;
- try (CloseableHttpClient client = HttpClients.createDefault()) {
+ try (CloseableHttpClient client = buildClient()) {
HttpGet httpGet = new HttpGet(url);
if (headers != null) {
headers.forEach(httpGet::addHeader);
@@ -44,7 +60,7 @@ public static String get(String url, Map headers) {
httpGet.addHeader(USER_AGENT_KEY, USER_AGENT_VALUE);
result = client.execute(httpGet, createResponseHandler());
} catch (IOException ioe) {
- ioe.printStackTrace();
+ LOGGER.log(WARNING, "Unable to finish the http get request.", ioe);
}
return result;
}
@@ -67,7 +83,7 @@ public static String getUserAgentPrefix() {
public static String post(String url, Map headers, String body, String contentType) {
String result = null;
- try (CloseableHttpClient client = HttpClients.createDefault()) {
+ try (CloseableHttpClient client = buildClient()) {
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader(USER_AGENT_KEY, USER_AGENT_VALUE);
if (headers != null) {
@@ -77,7 +93,7 @@ public static String post(String url, Map headers, String body,
httpPost.setEntity(new StringEntity(body, ContentType.create(contentType)));
result = client.execute(httpPost, createResponseHandler());
} catch (IOException ioe) {
- ioe.printStackTrace();
+ LOGGER.log(WARNING, "Unable to finish the http post request.", ioe);
}
return result;
}
@@ -94,4 +110,27 @@ private static ResponseHandler createResponseHandler() {
return result;
};
}
+
+ private static CloseableHttpClient buildClient() {
+ KeyStore keyStore = JREKeyStoreFactory.getDefaultKeyStore();
+
+ SSLContext sslContext = null;
+ try {
+ sslContext = SSLContexts
+ .custom()
+ .loadTrustMaterial(keyStore, null)
+ .build();
+ } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
+ LOGGER.log(WARNING, "Unable to build the ssl context.", e);
+ }
+
+ SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
+ sslContext, (HostnameVerifier) null);
+
+ PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(
+ RegistryBuilder.create()
+ .register("https", sslConnectionSocketFactory)
+ .build());
+ return HttpClients.custom().setConnectionManager(manager).build();
+ }
}
diff --git a/sdk/keyvault/azure-security-keyvault-jca/src/test/java/com/azure/security/keyvault/jca/implementation/JREKeyStoreFactoryTest.java b/sdk/keyvault/azure-security-keyvault-jca/src/test/java/com/azure/security/keyvault/jca/implementation/JREKeyStoreFactoryTest.java
new file mode 100644
index 0000000000000..2461d1a5f7122
--- /dev/null
+++ b/sdk/keyvault/azure-security-keyvault-jca/src/test/java/com/azure/security/keyvault/jca/implementation/JREKeyStoreFactoryTest.java
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.security.keyvault.jca.implementation;
+
+import com.azure.security.keyvault.jca.KeyVaultKeyStore;
+import org.junit.jupiter.api.Test;
+
+import java.security.KeyStore;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+public class JREKeyStoreFactoryTest {
+ @Test
+ public void test() {
+ KeyStore jreKeyStore = JREKeyStoreFactory.getDefaultKeyStore();
+ assertFalse(jreKeyStore.getType().equals(KeyVaultKeyStore.KEY_STORE_TYPE));
+ }
+}
diff --git a/sdk/keyvault/azure-security-keyvault-jca/src/test/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtilTest.java b/sdk/keyvault/azure-security-keyvault-jca/src/test/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtilTest.java
index 3b7a1f273aecc..faaf32670e239 100644
--- a/sdk/keyvault/azure-security-keyvault-jca/src/test/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtilTest.java
+++ b/sdk/keyvault/azure-security-keyvault-jca/src/test/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtilTest.java
@@ -7,7 +7,7 @@
import static com.azure.security.keyvault.jca.implementation.utils.HttpUtil.DEFAULT_USER_AGENT_VALUE_PREFIX;
import static com.azure.security.keyvault.jca.implementation.utils.HttpUtil.VERSION;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.*;
public class HttpUtilTest {
@@ -16,4 +16,12 @@ public void getUserAgentPrefixTest() {
assertEquals(DEFAULT_USER_AGENT_VALUE_PREFIX, HttpUtil.getUserAgentPrefix());
assertEquals(DEFAULT_USER_AGENT_VALUE_PREFIX + VERSION, HttpUtil.USER_AGENT_VALUE);
}
+
+ @Test
+ public void testCustomizedHttpsClient() {
+ String url = "https://google.com";
+ String result = HttpUtil.get(url, null);
+ assertNotNull(result);
+ assertFalse(result.isEmpty());
+ }
}