diff --git a/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransport.java b/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransport.java index 00a7673b3..f056024eb 100644 --- a/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransport.java +++ b/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransport.java @@ -14,10 +14,8 @@ package com.google.api.client.googleapis.apache.v5; -import com.google.api.client.googleapis.GoogleUtils; import com.google.api.client.googleapis.mtls.MtlsProvider; import com.google.api.client.googleapis.mtls.MtlsUtils; -import com.google.api.client.googleapis.util.Utils; import com.google.api.client.http.apache.v5.Apache5HttpTransport; import com.google.api.client.util.SslUtils; import com.google.common.annotations.Beta; @@ -48,11 +46,11 @@ public final class GoogleApache5HttpTransport { /** - * Returns a new instance of {@link Apache5HttpTransport} that uses {@link - * GoogleUtils#getCertificateTrustStore()} for the trusted certificates. If - * `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true", and the default - * client certificate key store from {@link Utils#loadDefaultMtlsKeyStore()} is not null, then the - * transport uses the default client certificate and is mutual TLS. + * Returns a new instance of {@link Apache5HttpTransport} that uses default jdk certificates for + * the trusted certificates. If `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to + * "true", and the default client certificate key store from {@link + * Utils#loadDefaultMtlsKeyStore()} is not null, then the transport uses the default client + * certificate and is mutual TLS. */ public static Apache5HttpTransport newTrustedTransport() throws GeneralSecurityException, IOException { @@ -61,9 +59,8 @@ public static Apache5HttpTransport newTrustedTransport() /** * {@link Beta}
- * Returns a new instance of {@link Apache5HttpTransport} that uses {@link - * GoogleUtils#getCertificateTrustStore()} for the trusted certificates. mtlsProvider can be used - * to configure mutual TLS for the transport. + * Returns a new instance of {@link Apache5HttpTransport} that uses default jdk certificates for + * the trusted certificates. mtlsProvider can be used to configure mutual TLS for the transport. * * @param mtlsProvider MtlsProvider to configure mutual TLS for the transport */ @@ -109,22 +106,20 @@ public SocketFactoryRegistryHandler(MtlsProvider mtlsProvider) mtlsKeyStorePassword = mtlsProvider.getKeyStorePassword(); } - // Use the included trust store - KeyStore trustStore = GoogleUtils.getCertificateTrustStore(); SSLContext sslContext = SslUtils.getTlsSslContext(); if (mtlsKeyStore != null && mtlsKeyStorePassword != null) { this.isMtls = true; SslUtils.initSslContext( sslContext, - trustStore, + null, SslUtils.getPkixTrustManagerFactory(), mtlsKeyStore, mtlsKeyStorePassword, SslUtils.getDefaultKeyManagerFactory()); } else { this.isMtls = false; - SslUtils.initSslContext(sslContext, trustStore, SslUtils.getPkixTrustManagerFactory()); + SslUtils.initSslContext(sslContext, null, SslUtils.getPkixTrustManagerFactory()); } LayeredConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext); diff --git a/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/ITGoogleApache5HttpTransportTest.java b/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/ITGoogleApache5HttpTransportTest.java index f8e9cbed1..8398606d3 100644 --- a/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/ITGoogleApache5HttpTransportTest.java +++ b/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/ITGoogleApache5HttpTransportTest.java @@ -30,10 +30,11 @@ public class ITGoogleApache5HttpTransportTest { @Test - public void testHttpRequestFailsWhenMakingRequestToSiteWithoutGoogleCerts() + public void testHttpRequestFailsWhenMakingRequestToSiteWithoutDefaultJdkCerts() throws GeneralSecurityException, IOException { Apache5HttpTransport apache5HttpTransport = GoogleApache5HttpTransport.newTrustedTransport(); - HttpGet httpGet = new HttpGet("https://maven.com/"); + // Use a self-signed certificate site that won't be trusted by default trust store + HttpGet httpGet = new HttpGet("https://self-signed.badssl.com/"); Exception exception = null; try { apache5HttpTransport @@ -43,7 +44,7 @@ public void testHttpRequestFailsWhenMakingRequestToSiteWithoutGoogleCerts() new HttpClientResponseHandler() { @Override public Void handleResponse(ClassicHttpResponse response) { - fail("Should not have been able to complete SSL request on non google site."); + fail("Should not have been able to complete SSL request with untrusted cert."); return null; } }); @@ -73,4 +74,23 @@ public Void handleResponse(ClassicHttpResponse response) { } }); } + + @Test + public void testHttpRequestPassesWhenMakingRequestToSiteContainedInDefaultCerts() + throws Exception { + Apache5HttpTransport apache5HttpTransport = GoogleApache5HttpTransport.newTrustedTransport(); + HttpGet httpGet = new HttpGet("https://central.sonatype.com/"); + + apache5HttpTransport + .getHttpClient() + .execute( + httpGet, + new HttpClientResponseHandler() { + @Override + public Void handleResponse(ClassicHttpResponse response) { + assertEquals(200, response.getCode()); + return null; + } + }); + } } diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/apache/v2/GoogleApacheHttpTransport.java b/google-api-client/src/main/java/com/google/api/client/googleapis/apache/v2/GoogleApacheHttpTransport.java index 93347cd3e..11c8dbbf3 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/apache/v2/GoogleApacheHttpTransport.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/apache/v2/GoogleApacheHttpTransport.java @@ -14,10 +14,8 @@ package com.google.api.client.googleapis.apache.v2; -import com.google.api.client.googleapis.GoogleUtils; import com.google.api.client.googleapis.mtls.MtlsProvider; import com.google.api.client.googleapis.mtls.MtlsUtils; -import com.google.api.client.googleapis.util.Utils; import com.google.api.client.http.apache.v2.ApacheHttpTransport; import com.google.api.client.util.Beta; import com.google.api.client.util.SslUtils; @@ -47,11 +45,11 @@ public final class GoogleApacheHttpTransport { /** - * Returns a new instance of {@link ApacheHttpTransport} that uses {@link - * GoogleUtils#getCertificateTrustStore()} for the trusted certificates. If - * `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true", and the default - * client certificate key store from {@link Utils#loadDefaultMtlsKeyStore()} is not null, then the - * transport uses the default client certificate and is mutual TLS. + * Returns a new instance of {@link ApacheHttpTransport} that uses default jdk certificates for + * the trusted certificates. If `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to + * "true", and the default client certificate key store from {@link + * Utils#loadDefaultMtlsKeyStore()} is not null, then the transport uses the default client + * certificate and is mutual TLS. */ public static ApacheHttpTransport newTrustedTransport() throws GeneralSecurityException, IOException { @@ -60,9 +58,8 @@ public static ApacheHttpTransport newTrustedTransport() /** * {@link Beta}
- * Returns a new instance of {@link ApacheHttpTransport} that uses {@link - * GoogleUtils#getCertificateTrustStore()} for the trusted certificates. mtlsProvider can be used - * to configure mutual TLS for the transport. + * Returns a new instance of {@link ApacheHttpTransport} that default jdk certs for the trusted + * certificates. mtlsProvider can be used to configure mutual TLS for the transport. * * @param mtlsProvider MtlsProvider to configure mutual TLS for the transport */ @@ -105,22 +102,20 @@ public SocketFactoryRegistryHandler(MtlsProvider mtlsProvider) mtlsKeyStorePassword = mtlsProvider.getKeyStorePassword(); } - // Use the included trust store - KeyStore trustStore = GoogleUtils.getCertificateTrustStore(); SSLContext sslContext = SslUtils.getTlsSslContext(); if (mtlsKeyStore != null && mtlsKeyStorePassword != null) { this.isMtls = true; SslUtils.initSslContext( sslContext, - trustStore, + null, SslUtils.getPkixTrustManagerFactory(), mtlsKeyStore, mtlsKeyStorePassword, SslUtils.getDefaultKeyManagerFactory()); } else { this.isMtls = false; - SslUtils.initSslContext(sslContext, trustStore, SslUtils.getPkixTrustManagerFactory()); + SslUtils.initSslContext(sslContext, null, SslUtils.getPkixTrustManagerFactory()); } LayeredConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext); diff --git a/google-api-client/src/test/java/com/google/api/client/googleapis/apache/v2/ITGoogleApacheHttpTransportTest.java b/google-api-client/src/test/java/com/google/api/client/googleapis/apache/v2/ITGoogleApacheHttpTransportTest.java new file mode 100644 index 000000000..ef02117ad --- /dev/null +++ b/google-api-client/src/test/java/com/google/api/client/googleapis/apache/v2/ITGoogleApacheHttpTransportTest.java @@ -0,0 +1,102 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under 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 KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.client.googleapis.apache.v2; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import com.google.api.client.http.apache.v2.ApacheHttpTransport; +import java.io.IOException; +import java.security.GeneralSecurityException; +import javax.net.ssl.SSLHandshakeException; +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.junit.Test; + +public class ITGoogleApacheHttpTransportTest { + + @Test + public void testHttpRequestFailsWhenMakingRequestToSiteWithoutDefaultJdkCerts() + throws GeneralSecurityException, IOException { + ApacheHttpTransport apacheHttpTransport = GoogleApacheHttpTransport.newTrustedTransport(); + // Use a self-signed certificate site that won't be trusted by default trust store + HttpGet httpGet = new HttpGet("https://self-signed.badssl.com/"); + Exception exception = null; + try { + apacheHttpTransport + .getHttpClient() + .execute( + httpGet, + new ResponseHandler() { + + @Override + public Object handleResponse(HttpResponse httpResponse) + throws ClientProtocolException, IOException { + fail("Should not have been able to complete SSL request with untrusted cert."); + return null; + } + }); + fail("Expected SSLHandshakeException was not thrown"); + } catch (SSLHandshakeException e) { + exception = e; + } + + assertNotNull(exception); + assertEquals(exception.getClass(), SSLHandshakeException.class); + } + + @Test + public void testHttpRequestPassesWhenMakingRequestToGoogleSite() throws Exception { + ApacheHttpTransport apacheHttpTransport = GoogleApacheHttpTransport.newTrustedTransport(); + HttpGet httpGet = new HttpGet("https://www.google.com/"); + + apacheHttpTransport + .getHttpClient() + .execute( + httpGet, + new ResponseHandler() { + @Override + public Object handleResponse(HttpResponse httpResponse) + throws ClientProtocolException, IOException { + assertEquals(200, httpResponse.getStatusLine().getStatusCode()); + return null; + } + }); + } + + @Test + public void testHttpRequestPassesWhenMakingRequestToSiteContainedInDefaultCerts() + throws Exception { + + ApacheHttpTransport apacheHttpTransport = GoogleApacheHttpTransport.newTrustedTransport(); + HttpGet httpGet = new HttpGet("https://central.sonatype.com/"); + + apacheHttpTransport + .getHttpClient() + .execute( + httpGet, + new ResponseHandler() { + @Override + public Object handleResponse(HttpResponse httpResponse) + throws ClientProtocolException, IOException { + assertEquals(200, httpResponse.getStatusLine().getStatusCode()); + return null; + } + }); + } +}