From e4fc0a0840f236fa93e4221fe7898fc560f56262 Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Thu, 15 Oct 2020 11:29:37 -0700 Subject: [PATCH 01/17] feat: support keystore in transport for mtls --- .../google/api/client/http/HttpTransport.java | 9 ++++ .../client/http/javanet/NetHttpTransport.java | 47 ++++++++++++++++--- .../com/google/api/client/util/SslUtils.java | 25 ++++++++++ 3 files changed, 75 insertions(+), 6 deletions(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/HttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/HttpTransport.java index d8b858c8e..a5672a71e 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/HttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/HttpTransport.java @@ -129,6 +129,15 @@ public boolean supportsMethod(String method) throws IOException { return Arrays.binarySearch(SUPPORTED_METHODS, method) >= 0; } + /** + * Returns whether the transport is mTLS. + * + * @return boolean indicating if the transport is mTLS. + */ + public boolean isMtls() { + return false; + } + /** * Builds a low level HTTP request for the given HTTP method. * diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index 3e90cb2c2..f402e863f 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -89,13 +89,16 @@ private static Proxy defaultProxy() { /** Host name verifier or {@code null} for the default. */ private final HostnameVerifier hostnameVerifier; + /** Whether the transport is mTLS. Default value is {@code false}. */ + private final boolean isMtls; + /** * Constructor with the default behavior. * *

Instead use {@link Builder} to modify behavior. */ public NetHttpTransport() { - this((ConnectionFactory) null, null, null); + this((ConnectionFactory) null, null, null, false); } /** @@ -104,10 +107,11 @@ public NetHttpTransport() { * system properties * @param sslSocketFactory SSL socket factory or {@code null} for the default * @param hostnameVerifier host name verifier or {@code null} for the default + * @param isMtls Whether the transport is mTLS. Default value is {@code false} */ NetHttpTransport( - Proxy proxy, SSLSocketFactory sslSocketFactory, HostnameVerifier hostnameVerifier) { - this(new DefaultConnectionFactory(proxy), sslSocketFactory, hostnameVerifier); + Proxy proxy, SSLSocketFactory sslSocketFactory, HostnameVerifier hostnameVerifier, boolean isMtls) { + this(new DefaultConnectionFactory(proxy), sslSocketFactory, hostnameVerifier, isMtls); } /** @@ -115,15 +119,18 @@ public NetHttpTransport() { * {@link DefaultConnectionFactory} is used * @param sslSocketFactory SSL socket factory or {@code null} for the default * @param hostnameVerifier host name verifier or {@code null} for the default + * @param isMtls Whether the transport is mTLS. Default value is {@code false} * @since 1.20 */ NetHttpTransport( ConnectionFactory connectionFactory, SSLSocketFactory sslSocketFactory, - HostnameVerifier hostnameVerifier) { + HostnameVerifier hostnameVerifier, + boolean isMtls) { this.connectionFactory = getConnectionFactory(connectionFactory); this.sslSocketFactory = sslSocketFactory; this.hostnameVerifier = hostnameVerifier; + this.isMtls = isMtls; } private ConnectionFactory getConnectionFactory(ConnectionFactory connectionFactory) { @@ -141,6 +148,11 @@ public boolean supportsMethod(String method) { return Arrays.binarySearch(SUPPORTED_METHODS, method) >= 0; } + @Override + public boolean isMtls() { + return this.isMtls; + } + @Override protected NetHttpRequest buildRequest(String method, String url) throws IOException { Preconditions.checkArgument(supportsMethod(method), "HTTP method %s not supported", method); @@ -189,6 +201,9 @@ public static final class Builder { */ private ConnectionFactory connectionFactory; + /** Whether the transport is mTLS. Default value is {@code false}. */ + private boolean isMtls; + /** * Sets the HTTP proxy or {@code null} to use the proxy settings from system @@ -275,6 +290,26 @@ public Builder trustCertificates(KeyStore trustStore) throws GeneralSecurityExce return setSslSocketFactory(sslContext.getSocketFactory()); } + /** + * Sets the SSL socket factory based on a root certificate trust store and a client + * certificate key store. + * + * @param trustStore certificate trust store (use for example {@link SecurityUtils#loadKeyStore} + * or {@link SecurityUtils#loadKeyStoreFromCertificates}) + * @param keyStore key store for client certificate and key + * @param keystorePassword password for keyStore parameter + */ + public Builder trustCertificates(KeyStore trustStore, KeyStore keyStore, char[] keystorePassword) throws GeneralSecurityException { + if (keyStore != null) { + this.isMtls = true; + } + SSLContext sslContext = SslUtils.getTlsSslContext(); + SslUtils.initSslContext(sslContext, trustStore, SslUtils.getPkixTrustManagerFactory(), + keyStore, keystorePassword, SslUtils.getDefaultKeyManagerFactory()); + return setSslSocketFactory(sslContext.getSocketFactory()); + } + + /** * {@link Beta}
* Disables validating server SSL certificates by setting the SSL socket factory using {@link @@ -319,8 +354,8 @@ public NetHttpTransport build() { setProxy(defaultProxy()); } return this.proxy == null - ? new NetHttpTransport(connectionFactory, sslSocketFactory, hostnameVerifier) - : new NetHttpTransport(this.proxy, sslSocketFactory, hostnameVerifier); + ? new NetHttpTransport(connectionFactory, sslSocketFactory, hostnameVerifier, isMtls) + : new NetHttpTransport(this.proxy, sslSocketFactory, hostnameVerifier, isMtls); } } } diff --git a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java index d4ed4f7cf..e40b41809 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java @@ -109,6 +109,31 @@ public static SSLContext initSslContext( return sslContext; } + /** + * Initializes the SSL context to the trust managers supplied by the trust manager factory for the + * given trust store, and to the key managers supplied by the key manager factory for the given + * key store. + * + * @param sslContext SSL context (for example {@link SSLContext#getInstance}) + * @param trustStore key store for certificates to trust (for example {@link + * SecurityUtils#getJavaKeyStore()}) + * @param trustManagerFactory trust manager factory (for example {@link + * #getPkixTrustManagerFactory()}) + * @param keyStore key store for client certificate and key + * @param keystorePassword password for keyStore parameter + * @param keyManagerFactory key manager factory (for example {@link + * #getDefaultKeyManagerFactory()}) + */ + public static SSLContext initSslContext( + SSLContext sslContext, KeyStore trustStore, TrustManagerFactory trustManagerFactory, + KeyStore keyStore, char[] keystorePassword, KeyManagerFactory keyManagerFactory) + throws GeneralSecurityException { + trustManagerFactory.init(trustStore); + keyManagerFactory.init(keyStore, keystorePassword); + sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); + return sslContext; + } + /** * {@link Beta}
* Returns an SSL context in which all X.509 certificates are trusted. From 3f3d403694db37717eff0f9f49e0b808370b39da Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Thu, 15 Oct 2020 12:02:52 -0700 Subject: [PATCH 02/17] fix format --- .../google/api/client/http/HttpTransport.java | 2 +- .../client/http/javanet/NetHttpTransport.java | 23 +++++++++++++------ .../com/google/api/client/util/SslUtils.java | 13 +++++++---- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/HttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/HttpTransport.java index a5672a71e..d4fad3f87 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/HttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/HttpTransport.java @@ -131,7 +131,7 @@ public boolean supportsMethod(String method) throws IOException { /** * Returns whether the transport is mTLS. - * + * * @return boolean indicating if the transport is mTLS. */ public boolean isMtls() { diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index f402e863f..a9726d138 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -110,7 +110,10 @@ public NetHttpTransport() { * @param isMtls Whether the transport is mTLS. Default value is {@code false} */ NetHttpTransport( - Proxy proxy, SSLSocketFactory sslSocketFactory, HostnameVerifier hostnameVerifier, boolean isMtls) { + Proxy proxy, + SSLSocketFactory sslSocketFactory, + HostnameVerifier hostnameVerifier, + boolean isMtls) { this(new DefaultConnectionFactory(proxy), sslSocketFactory, hostnameVerifier, isMtls); } @@ -291,25 +294,31 @@ public Builder trustCertificates(KeyStore trustStore) throws GeneralSecurityExce } /** - * Sets the SSL socket factory based on a root certificate trust store and a client - * certificate key store. + * Sets the SSL socket factory based on a root certificate trust store and a client certificate + * key store. * * @param trustStore certificate trust store (use for example {@link SecurityUtils#loadKeyStore} * or {@link SecurityUtils#loadKeyStoreFromCertificates}) * @param keyStore key store for client certificate and key * @param keystorePassword password for keyStore parameter */ - public Builder trustCertificates(KeyStore trustStore, KeyStore keyStore, char[] keystorePassword) throws GeneralSecurityException { + public Builder trustCertificates( + KeyStore trustStore, KeyStore keyStore, char[] keystorePassword) + throws GeneralSecurityException { if (keyStore != null) { this.isMtls = true; } SSLContext sslContext = SslUtils.getTlsSslContext(); - SslUtils.initSslContext(sslContext, trustStore, SslUtils.getPkixTrustManagerFactory(), - keyStore, keystorePassword, SslUtils.getDefaultKeyManagerFactory()); + SslUtils.initSslContext( + sslContext, + trustStore, + SslUtils.getPkixTrustManagerFactory(), + keyStore, + keystorePassword, + SslUtils.getDefaultKeyManagerFactory()); return setSslSocketFactory(sslContext.getSocketFactory()); } - /** * {@link Beta}
* Disables validating server SSL certificates by setting the SSL socket factory using {@link diff --git a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java index e40b41809..b2321b053 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java @@ -121,16 +121,21 @@ public static SSLContext initSslContext( * #getPkixTrustManagerFactory()}) * @param keyStore key store for client certificate and key * @param keystorePassword password for keyStore parameter - * @param keyManagerFactory key manager factory (for example {@link + * @param keyManagerFactory key manager factory (for example {@link * #getDefaultKeyManagerFactory()}) */ public static SSLContext initSslContext( - SSLContext sslContext, KeyStore trustStore, TrustManagerFactory trustManagerFactory, - KeyStore keyStore, char[] keystorePassword, KeyManagerFactory keyManagerFactory) + SSLContext sslContext, + KeyStore trustStore, + TrustManagerFactory trustManagerFactory, + KeyStore keyStore, + char[] keystorePassword, + KeyManagerFactory keyManagerFactory) throws GeneralSecurityException { trustManagerFactory.init(trustStore); keyManagerFactory.init(keyStore, keystorePassword); - sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); + sslContext.init( + keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); return sslContext; } From 0feec0554ab98e5fbb079c2c599f40608016c93e Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Thu, 15 Oct 2020 12:32:31 -0700 Subject: [PATCH 03/17] update code --- .../com/google/api/client/http/javanet/NetHttpTransport.java | 2 +- .../src/main/java/com/google/api/client/util/SslUtils.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index a9726d138..ef3f618fc 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -303,7 +303,7 @@ public Builder trustCertificates(KeyStore trustStore) throws GeneralSecurityExce * @param keystorePassword password for keyStore parameter */ public Builder trustCertificates( - KeyStore trustStore, KeyStore keyStore, char[] keystorePassword) + KeyStore trustStore, KeyStore keyStore, String keystorePassword) throws GeneralSecurityException { if (keyStore != null) { this.isMtls = true; diff --git a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java index b2321b053..adea39186 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java @@ -129,11 +129,11 @@ public static SSLContext initSslContext( KeyStore trustStore, TrustManagerFactory trustManagerFactory, KeyStore keyStore, - char[] keystorePassword, + String keystorePassword, KeyManagerFactory keyManagerFactory) throws GeneralSecurityException { trustManagerFactory.init(trustStore); - keyManagerFactory.init(keyStore, keystorePassword); + keyManagerFactory.init(keyStore, keystorePassword.toCharArray()); sslContext.init( keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); return sslContext; From a71a009c8d2f87db12f22eecdc3482ef983f6ea1 Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Fri, 16 Oct 2020 00:39:00 -0700 Subject: [PATCH 04/17] add tests --- .../client/http/javanet/NetHttpTransport.java | 2 +- .../http/javanet/NetHttpTransportTest.java | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index ef3f618fc..93b888797 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -305,7 +305,7 @@ public Builder trustCertificates(KeyStore trustStore) throws GeneralSecurityExce public Builder trustCertificates( KeyStore trustStore, KeyStore keyStore, String keystorePassword) throws GeneralSecurityException { - if (keyStore != null) { + if (keyStore != null && keyStore.size() > 0) { this.isMtls = true; } SSLContext sslContext = SslUtils.getTlsSslContext(); diff --git a/google-http-client/src/test/java/com/google/api/client/http/javanet/NetHttpTransportTest.java b/google-http-client/src/test/java/com/google/api/client/http/javanet/NetHttpTransportTest.java index a1bc3b348..338761205 100644 --- a/google-http-client/src/test/java/com/google/api/client/http/javanet/NetHttpTransportTest.java +++ b/google-http-client/src/test/java/com/google/api/client/http/javanet/NetHttpTransportTest.java @@ -23,6 +23,7 @@ import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.security.KeyStore; import junit.framework.TestCase; /** @@ -36,6 +37,25 @@ public class NetHttpTransportTest extends TestCase { "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE" }; + public void testMtls() throws Exception { + KeyStore trustStore = KeyStore.getInstance("JKS"); + KeyStore keyStore = KeyStore.getInstance("PKCS12"); + keyStore.load( + this.getClass() + .getClassLoader() + .getResourceAsStream("com/google/api/client/util/secret.p12"), + "notasecret".toCharArray()); + + NetHttpTransport transport = + new NetHttpTransport.Builder().trustCertificates(trustStore).build(); + assertFalse(transport.isMtls()); + transport = + new NetHttpTransport.Builder() + .trustCertificates(trustStore, keyStore, "notasecret") + .build(); + assertTrue(transport.isMtls()); + } + public void testExecute_mock() throws Exception { for (String method : METHODS) { boolean isPutOrPost = method.equals("PUT") || method.equals("POST"); From 3c10eaa3d10ce801b47bc221cd496c45807cd8a3 Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Fri, 16 Oct 2020 10:45:35 -0700 Subject: [PATCH 05/17] update test and doc --- .../api/client/http/javanet/NetHttpTransport.java | 4 ++-- .../client/http/javanet/NetHttpTransportTest.java | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index 93b888797..6227475d7 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -295,11 +295,11 @@ public Builder trustCertificates(KeyStore trustStore) throws GeneralSecurityExce /** * Sets the SSL socket factory based on a root certificate trust store and a client certificate - * key store. + * key store. The client certificate key store will be used to establish mutual TLS. * * @param trustStore certificate trust store (use for example {@link SecurityUtils#loadKeyStore} * or {@link SecurityUtils#loadKeyStoreFromCertificates}) - * @param keyStore key store for client certificate and key + * @param keyStore key store for client certificate and key. It is used to establish mutual TLS. * @param keystorePassword password for keyStore parameter */ public Builder trustCertificates( diff --git a/google-http-client/src/test/java/com/google/api/client/http/javanet/NetHttpTransportTest.java b/google-http-client/src/test/java/com/google/api/client/http/javanet/NetHttpTransportTest.java index 338761205..338236e9b 100644 --- a/google-http-client/src/test/java/com/google/api/client/http/javanet/NetHttpTransportTest.java +++ b/google-http-client/src/test/java/com/google/api/client/http/javanet/NetHttpTransportTest.java @@ -37,9 +37,19 @@ public class NetHttpTransportTest extends TestCase { "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE" }; - public void testMtls() throws Exception { + public void testNotMtlsWithoutClientCert() throws Exception { + KeyStore trustStore = KeyStore.getInstance("JKS"); + + NetHttpTransport transport = + new NetHttpTransport.Builder().trustCertificates(trustStore).build(); + assertFalse(transport.isMtls()); + } + + public void testIsMtlsWithClientCert() throws Exception { KeyStore trustStore = KeyStore.getInstance("JKS"); KeyStore keyStore = KeyStore.getInstance("PKCS12"); + + // Load client certificate and private key from secret.p12 file. keyStore.load( this.getClass() .getClassLoader() @@ -47,9 +57,6 @@ public void testMtls() throws Exception { "notasecret".toCharArray()); NetHttpTransport transport = - new NetHttpTransport.Builder().trustCertificates(trustStore).build(); - assertFalse(transport.isMtls()); - transport = new NetHttpTransport.Builder() .trustCertificates(trustStore, keyStore, "notasecret") .build(); From 275bad0a08b8859b41d47b79441f70ba4bc5c048 Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Thu, 22 Oct 2020 19:24:59 -0700 Subject: [PATCH 06/17] update names --- .../api/client/http/javanet/NetHttpTransport.java | 12 ++++++------ .../java/com/google/api/client/util/SslUtils.java | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index 6227475d7..4601d97f0 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -299,13 +299,13 @@ public Builder trustCertificates(KeyStore trustStore) throws GeneralSecurityExce * * @param trustStore certificate trust store (use for example {@link SecurityUtils#loadKeyStore} * or {@link SecurityUtils#loadKeyStoreFromCertificates}) - * @param keyStore key store for client certificate and key. It is used to establish mutual TLS. - * @param keystorePassword password for keyStore parameter + * @param mtlsKeyStore key store for client certificate and key to establish mutual TLS. + * @param mtlsKeystorePassword password for mtlsKeyStore parameter */ public Builder trustCertificates( - KeyStore trustStore, KeyStore keyStore, String keystorePassword) + KeyStore trustStore, KeyStore mtlsKeyStore, String mtlsKeystorePassword) throws GeneralSecurityException { - if (keyStore != null && keyStore.size() > 0) { + if (mtlsKeyStore != null && mtlsKeyStore.size() > 0) { this.isMtls = true; } SSLContext sslContext = SslUtils.getTlsSslContext(); @@ -313,8 +313,8 @@ public Builder trustCertificates( sslContext, trustStore, SslUtils.getPkixTrustManagerFactory(), - keyStore, - keystorePassword, + mtlsKeyStore, + mtlsKeystorePassword, SslUtils.getDefaultKeyManagerFactory()); return setSslSocketFactory(sslContext.getSocketFactory()); } diff --git a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java index adea39186..f4c2e3a4b 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java @@ -119,8 +119,8 @@ public static SSLContext initSslContext( * SecurityUtils#getJavaKeyStore()}) * @param trustManagerFactory trust manager factory (for example {@link * #getPkixTrustManagerFactory()}) - * @param keyStore key store for client certificate and key - * @param keystorePassword password for keyStore parameter + * @param mtlsKeyStore key store for client certificate and key to establish mutual TLS + * @param mtlsKeystorePassword password for mtlsKeyStore parameter * @param keyManagerFactory key manager factory (for example {@link * #getDefaultKeyManagerFactory()}) */ @@ -128,12 +128,12 @@ public static SSLContext initSslContext( SSLContext sslContext, KeyStore trustStore, TrustManagerFactory trustManagerFactory, - KeyStore keyStore, - String keystorePassword, + KeyStore mtlsKeyStore, + String mtlsKeystorePassword, KeyManagerFactory keyManagerFactory) throws GeneralSecurityException { trustManagerFactory.init(trustStore); - keyManagerFactory.init(keyStore, keystorePassword.toCharArray()); + keyManagerFactory.init(mtlsKeyStore, mtlsKeystorePassword.toCharArray()); sslContext.init( keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); return sslContext; From e21791c6ae750d70fc89710304e429de2b141cb1 Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Fri, 23 Oct 2020 01:18:26 -0700 Subject: [PATCH 07/17] create keystore from cert and key string --- .../google/api/client/util/SecurityUtils.java | 59 +++++++++++++++++++ .../api/client/util/SecurityUtilsTest.java | 55 +++++++++++++++++ .../com/google/api/client/util/cert.pem | 14 +++++ .../com/google/api/client/util/privateKey.pem | 16 +++++ 4 files changed, 144 insertions(+) create mode 100644 google-http-client/src/test/resources/com/google/api/client/util/cert.pem create mode 100644 google-http-client/src/test/resources/com/google/api/client/util/privateKey.pem diff --git a/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java index cf08e03ad..0fab3fede 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java @@ -17,6 +17,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.KeyFactory; @@ -31,6 +32,7 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; import java.util.List; import javax.net.ssl.X509TrustManager; @@ -258,5 +260,62 @@ public static void loadKeyStoreFromCertificates( } } + /** + * Create a keystore for mutual TLS with the certificate and private key provided. + * + *

certAndKey should have the following format: + * + *

+   * -----BEGIN CERTIFICATE-----
+   * ......
+   * -----END CERTIFICATE------
+   * ----BEGIN PRIVATE KEY-----
+   * ......
+   * -----END PRIVATE KEY-----
+   * 
+ * + * @param certAndKey Concatenation of a x509 certificate PEM string and a PKCS#8 unencrypted + * private key PEM string. + * @return keystore for mutual TLS. + */ + public static KeyStore createMtlsKeyStore(String certAndKey) + throws GeneralSecurityException, IOException { + KeyStore keystore = KeyStore.getInstance("JKS"); + try { + keystore.load(null); + } catch (IOException ignored) { + // shouldn't throw any exception to load a null keystore. + } + + byte[] certAndKeyBytes = certAndKey.getBytes(); + + // Read the certificate. + InputStreamReader reader = new InputStreamReader(new ByteArrayInputStream(certAndKeyBytes)); + PemReader.Section section = PemReader.readFirstSectionAndClose(reader, "CERTIFICATE"); + if (section == null) { + throw new IllegalArgumentException("certificate is missing from certAndKey string"); + } + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + X509Certificate cert = + (X509Certificate) + certFactory.generateCertificate( + new ByteArrayInputStream(section.getBase64DecodedBytes())); + + // Read the private key. + reader = new InputStreamReader(new ByteArrayInputStream(certAndKeyBytes)); + section = PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY"); + if (section == null) { + throw new IllegalArgumentException("private key is missing from certAndKey string"); + } + PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(section.getBase64DecodedBytes()); + PrivateKey key = + KeyFactory.getInstance(cert.getPublicKey().getAlgorithm()).generatePrivate(keySpecPKCS8); + + // Fit the certificate and private key into the keystore. + keystore.setKeyEntry("alias", key, new char[] {}, new X509Certificate[] {cert}); + + return keystore; + } + private SecurityUtils() {} } diff --git a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java index b9f91fd1e..f17b29026 100644 --- a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java +++ b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java @@ -14,9 +14,16 @@ package com.google.api.client.util; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + import com.google.api.client.testing.json.webtoken.TestCertificates; import com.google.api.client.testing.util.SecurityTestUtils; +import com.google.common.io.Resources; import java.io.ByteArrayInputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.security.KeyStore; import java.security.PrivateKey; import java.security.Signature; import java.security.cert.X509Certificate; @@ -25,6 +32,7 @@ import javax.net.ssl.X509TrustManager; import junit.framework.TestCase; import org.junit.Assert; +import org.junit.function.ThrowingRunnable; /** * Tests {@link SecurityUtils}. @@ -160,4 +168,51 @@ public void testVerifyX509() throws Exception { public void testVerifyX509WrongCa() throws Exception { assertNull(verifyX509(TestCertificates.BOGUS_CA_CERT)); } + + public void testCreateMtlsKeyStoreNoCert() throws Exception { + URL url = getClass().getClassLoader().getResource("com/google/api/client/util/privateKey.pem"); + final String certMissing = Resources.toString(url, StandardCharsets.UTF_8); + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + new ThrowingRunnable() { + @Override + public void run() throws Throwable { + SecurityUtils.createMtlsKeyStore(certMissing); + } + }); + assertThat(exception) + .hasMessageThat() + .isEqualTo("certificate is missing from certAndKey string"); + } + + public void testCreateMtlsKeyStoreNoPrivateKey() throws Exception { + URL url = getClass().getClassLoader().getResource("com/google/api/client/util/cert.pem"); + final String privateKeyMissing = Resources.toString(url, StandardCharsets.UTF_8); + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + new ThrowingRunnable() { + @Override + public void run() throws Throwable { + SecurityUtils.createMtlsKeyStore(privateKeyMissing); + } + }); + assertThat(exception) + .hasMessageThat() + .isEqualTo("private key is missing from certAndKey string"); + } + + public void testCreateMtlsKeyStoreSuccess() throws Exception { + URL url = getClass().getClassLoader().getResource("com/google/api/client/util/cert.pem"); + String cert = Resources.toString(url, StandardCharsets.UTF_8); + + url = getClass().getClassLoader().getResource("com/google/api/client/util/privateKey.pem"); + String privateKey = Resources.toString(url, StandardCharsets.UTF_8); + + String certAndKey = cert + "\n" + privateKey; + KeyStore mtlsKeyStore = SecurityUtils.createMtlsKeyStore(certAndKey); + + assertEquals(mtlsKeyStore.size(), 1); + } } diff --git a/google-http-client/src/test/resources/com/google/api/client/util/cert.pem b/google-http-client/src/test/resources/com/google/api/client/util/cert.pem new file mode 100644 index 000000000..56e1319bf --- /dev/null +++ b/google-http-client/src/test/resources/com/google/api/client/util/cert.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICGzCCAYSgAwIBAgIIWrt6xtmHPs4wDQYJKoZIhvcNAQEFBQAwMzExMC8GA1UE +AxMoMTAwOTEyMDcyNjg3OC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbTAeFw0x +MjEyMDExNjEwNDRaFw0yMjExMjkxNjEwNDRaMDMxMTAvBgNVBAMTKDEwMDkxMjA3 +MjY4NzguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBAL1SdY8jTUVU7O4/XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQ +GLW8Iftx9wfXe1zuaehJSgLcyCxazfyJoN3RiONBihBqWY6d3lQKqkgsRTNZkdFJ +Wdzl/6CxhK9sojh2p0r3tydtv9iwq5fuuWIvtODtT98EgphhncQAqkKoF3zVAgMB +AAGjODA2MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQM +MAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAD8XQEqzGePa9VrvtEGpf+R4 +fkxKbcYAzqYq202nKu0kfjhIYkYSBj6gi348YaxE64yu60TVl42l5HThmswUheW4 +uQIaq36JvwvsDP5Zoj5BgiNSnDAFQp+jJFBRUA5vooJKgKgMDf/r/DCOsbO6VJF1 +kWwa9n19NFiV0z3m6isj +-----END CERTIFICATE----- \ No newline at end of file diff --git a/google-http-client/src/test/resources/com/google/api/client/util/privateKey.pem b/google-http-client/src/test/resources/com/google/api/client/util/privateKey.pem new file mode 100644 index 000000000..dd13e1c09 --- /dev/null +++ b/google-http-client/src/test/resources/com/google/api/client/util/privateKey.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL1SdY8jTUVU7O4/ +XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQGLW8Iftx9wfXe1zuaehJSgLcyCxazfyJ +oN3RiONBihBqWY6d3lQKqkgsRTNZkdFJWdzl/6CxhK9sojh2p0r3tydtv9iwq5fu +uWIvtODtT98EgphhncQAqkKoF3zVAgMBAAECgYB51B9cXe4yiGTzJ4pOKpHGySAy +sC1F/IjXt2eeD3PuKv4m/hL4l7kScpLx0+NJuQ4j8U2UK/kQOdrGANapB1ZbMZAK +/q0xmIUzdNIDiGSoTXGN2mEfdsEpQ/Xiv0lyhYBBPC/K4sYIpHccnhSRQUZlWLLY +lE5cFNKC9b7226mNvQJBAPt0hfCNIN0kUYOA9jdLtx7CE4ySGMPf5KPBuzPd8ty1 +fxaFm9PB7B76VZQYmHcWy8rT5XjoLJHrmGW1ZvP+iDsCQQDAvnKoarPOGb5iJfkq +RrA4flf1TOlf+1+uqIOJ94959jkkJeb0gv/TshDnm6/bWn+1kJylQaKygCizwPwB +Z84vAkA0Duur4YvsPJijoQ9YY1SGCagCcjyuUKwFOxaGpmyhRPIKt56LOJqpzyno +fy8ReKa4VyYq4eZYT249oFCwMwIBAkAROPNF2UL3x5UbcAkznd1hLujtIlI4IV4L +XUNjsJtBap7we/KHJq11XRPlniO4lf2TW7iji5neGVWJulTKS1xBAkAerktk4Hsw +ErUaUG1s/d+Sgc8e/KMeBElV+NxGhcWEeZtfHMn/6VOlbzY82JyvC9OKC80A5CAE +VUV6b25kqrcu +-----END PRIVATE KEY----- \ No newline at end of file From 2edb1346b65ef8cc4fe51dfaa28377785240fff0 Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Mon, 26 Oct 2020 16:52:39 -0700 Subject: [PATCH 08/17] change certAndKey from string to inputstream --- .../google/api/client/util/SecurityUtils.java | 61 +++++++++---------- .../api/client/util/SecurityUtilsTest.java | 15 +++-- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java index 0fab3fede..953fc9366 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java @@ -263,51 +263,48 @@ public static void loadKeyStoreFromCertificates( /** * Create a keystore for mutual TLS with the certificate and private key provided. * - *

certAndKey should have the following format: - * - *

-   * -----BEGIN CERTIFICATE-----
-   * ......
-   * -----END CERTIFICATE------
-   * ----BEGIN PRIVATE KEY-----
-   * ......
-   * -----END PRIVATE KEY-----
-   * 
- * - * @param certAndKey Concatenation of a x509 certificate PEM string and a PKCS#8 unencrypted - * private key PEM string. + * @param certAndKey Certificate and private key input stream. The stream should contain one + * certificate and one unencrypted private key. If there are multiple certificates, only the + * first certificate will be used. * @return keystore for mutual TLS. */ - public static KeyStore createMtlsKeyStore(String certAndKey) + public static KeyStore createMtlsKeyStore(InputStream certAndKey) throws GeneralSecurityException, IOException { KeyStore keystore = KeyStore.getInstance("JKS"); - try { - keystore.load(null); - } catch (IOException ignored) { - // shouldn't throw any exception to load a null keystore. - } + keystore.load(null); + + PemReader.Section certSection = null; + PemReader.Section keySection = null; + PemReader reader = new PemReader(new InputStreamReader(certAndKey)); + + while (certSection == null || keySection == null) { + // Read the certificate and private key. + PemReader.Section section = reader.readNextSection(); + if (section == null) { + break; + } - byte[] certAndKeyBytes = certAndKey.getBytes(); + if ("CERTIFICATE".equals(section.getTitle())) { + certSection = section; + } else if ("PRIVATE KEY".equals(section.getTitle())) { + keySection = section; + } + } - // Read the certificate. - InputStreamReader reader = new InputStreamReader(new ByteArrayInputStream(certAndKeyBytes)); - PemReader.Section section = PemReader.readFirstSectionAndClose(reader, "CERTIFICATE"); - if (section == null) { + if (certSection == null) { throw new IllegalArgumentException("certificate is missing from certAndKey string"); } + if (keySection == null) { + throw new IllegalArgumentException("private key is missing from certAndKey string"); + } + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) certFactory.generateCertificate( - new ByteArrayInputStream(section.getBase64DecodedBytes())); + new ByteArrayInputStream(certSection.getBase64DecodedBytes())); - // Read the private key. - reader = new InputStreamReader(new ByteArrayInputStream(certAndKeyBytes)); - section = PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY"); - if (section == null) { - throw new IllegalArgumentException("private key is missing from certAndKey string"); - } - PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(section.getBase64DecodedBytes()); + PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(keySection.getBase64DecodedBytes()); PrivateKey key = KeyFactory.getInstance(cert.getPublicKey().getAlgorithm()).generatePrivate(keySpecPKCS8); diff --git a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java index f17b29026..ba4aebc70 100644 --- a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java +++ b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java @@ -21,6 +21,7 @@ import com.google.api.client.testing.util.SecurityTestUtils; import com.google.common.io.Resources; import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.KeyStore; @@ -170,8 +171,10 @@ public void testVerifyX509WrongCa() throws Exception { } public void testCreateMtlsKeyStoreNoCert() throws Exception { - URL url = getClass().getClassLoader().getResource("com/google/api/client/util/privateKey.pem"); - final String certMissing = Resources.toString(url, StandardCharsets.UTF_8); + final InputStream certMissing = + getClass() + .getClassLoader() + .getResourceAsStream("com/google/api/client/util/privateKey.pem"); IllegalArgumentException exception = assertThrows( IllegalArgumentException.class, @@ -187,8 +190,8 @@ public void run() throws Throwable { } public void testCreateMtlsKeyStoreNoPrivateKey() throws Exception { - URL url = getClass().getClassLoader().getResource("com/google/api/client/util/cert.pem"); - final String privateKeyMissing = Resources.toString(url, StandardCharsets.UTF_8); + final InputStream privateKeyMissing = + getClass().getClassLoader().getResourceAsStream("com/google/api/client/util/cert.pem"); IllegalArgumentException exception = assertThrows( IllegalArgumentException.class, @@ -210,7 +213,9 @@ public void testCreateMtlsKeyStoreSuccess() throws Exception { url = getClass().getClassLoader().getResource("com/google/api/client/util/privateKey.pem"); String privateKey = Resources.toString(url, StandardCharsets.UTF_8); - String certAndKey = cert + "\n" + privateKey; + String certAndKeyString = privateKey + "\n" + cert; + ByteArrayInputStream certAndKey = new ByteArrayInputStream(certAndKeyString.getBytes()); + KeyStore mtlsKeyStore = SecurityUtils.createMtlsKeyStore(certAndKey); assertEquals(mtlsKeyStore.size(), 1); From 09847d7a4d836e617e4a5512553dfc6feb7d0fae Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Mon, 26 Oct 2020 18:48:15 -0700 Subject: [PATCH 09/17] add mtls file --- .../api/client/util/SecurityUtilsTest.java | 15 +++------- .../google/api/client/util/mtlsCertAndKey.pem | 30 +++++++++++++++++++ 2 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 google-http-client/src/test/resources/com/google/api/client/util/mtlsCertAndKey.pem diff --git a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java index ba4aebc70..10b7bb612 100644 --- a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java +++ b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java @@ -19,11 +19,8 @@ import com.google.api.client.testing.json.webtoken.TestCertificates; import com.google.api.client.testing.util.SecurityTestUtils; -import com.google.common.io.Resources; import java.io.ByteArrayInputStream; import java.io.InputStream; -import java.net.URL; -import java.nio.charset.StandardCharsets; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Signature; @@ -207,14 +204,10 @@ public void run() throws Throwable { } public void testCreateMtlsKeyStoreSuccess() throws Exception { - URL url = getClass().getClassLoader().getResource("com/google/api/client/util/cert.pem"); - String cert = Resources.toString(url, StandardCharsets.UTF_8); - - url = getClass().getClassLoader().getResource("com/google/api/client/util/privateKey.pem"); - String privateKey = Resources.toString(url, StandardCharsets.UTF_8); - - String certAndKeyString = privateKey + "\n" + cert; - ByteArrayInputStream certAndKey = new ByteArrayInputStream(certAndKeyString.getBytes()); + InputStream certAndKey = + getClass() + .getClassLoader() + .getResourceAsStream("com/google/api/client/util/mtlsCertAndKey.pem"); KeyStore mtlsKeyStore = SecurityUtils.createMtlsKeyStore(certAndKey); diff --git a/google-http-client/src/test/resources/com/google/api/client/util/mtlsCertAndKey.pem b/google-http-client/src/test/resources/com/google/api/client/util/mtlsCertAndKey.pem new file mode 100644 index 000000000..d6c045125 --- /dev/null +++ b/google-http-client/src/test/resources/com/google/api/client/util/mtlsCertAndKey.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIICGzCCAYSgAwIBAgIIWrt6xtmHPs4wDQYJKoZIhvcNAQEFBQAwMzExMC8GA1UE +AxMoMTAwOTEyMDcyNjg3OC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbTAeFw0x +MjEyMDExNjEwNDRaFw0yMjExMjkxNjEwNDRaMDMxMTAvBgNVBAMTKDEwMDkxMjA3 +MjY4NzguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBAL1SdY8jTUVU7O4/XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQ +GLW8Iftx9wfXe1zuaehJSgLcyCxazfyJoN3RiONBihBqWY6d3lQKqkgsRTNZkdFJ +Wdzl/6CxhK9sojh2p0r3tydtv9iwq5fuuWIvtODtT98EgphhncQAqkKoF3zVAgMB +AAGjODA2MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQM +MAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAD8XQEqzGePa9VrvtEGpf+R4 +fkxKbcYAzqYq202nKu0kfjhIYkYSBj6gi348YaxE64yu60TVl42l5HThmswUheW4 +uQIaq36JvwvsDP5Zoj5BgiNSnDAFQp+jJFBRUA5vooJKgKgMDf/r/DCOsbO6VJF1 +kWwa9n19NFiV0z3m6isj +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL1SdY8jTUVU7O4/ +XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQGLW8Iftx9wfXe1zuaehJSgLcyCxazfyJ +oN3RiONBihBqWY6d3lQKqkgsRTNZkdFJWdzl/6CxhK9sojh2p0r3tydtv9iwq5fu +uWIvtODtT98EgphhncQAqkKoF3zVAgMBAAECgYB51B9cXe4yiGTzJ4pOKpHGySAy +sC1F/IjXt2eeD3PuKv4m/hL4l7kScpLx0+NJuQ4j8U2UK/kQOdrGANapB1ZbMZAK +/q0xmIUzdNIDiGSoTXGN2mEfdsEpQ/Xiv0lyhYBBPC/K4sYIpHccnhSRQUZlWLLY +lE5cFNKC9b7226mNvQJBAPt0hfCNIN0kUYOA9jdLtx7CE4ySGMPf5KPBuzPd8ty1 +fxaFm9PB7B76VZQYmHcWy8rT5XjoLJHrmGW1ZvP+iDsCQQDAvnKoarPOGb5iJfkq +RrA4flf1TOlf+1+uqIOJ94959jkkJeb0gv/TshDnm6/bWn+1kJylQaKygCizwPwB +Z84vAkA0Duur4YvsPJijoQ9YY1SGCagCcjyuUKwFOxaGpmyhRPIKt56LOJqpzyno +fy8ReKa4VyYq4eZYT249oFCwMwIBAkAROPNF2UL3x5UbcAkznd1hLujtIlI4IV4L +XUNjsJtBap7we/KHJq11XRPlniO4lf2TW7iji5neGVWJulTKS1xBAkAerktk4Hsw +ErUaUG1s/d+Sgc8e/KMeBElV+NxGhcWEeZtfHMn/6VOlbzY82JyvC9OKC80A5CAE +VUV6b25kqrcu +-----END PRIVATE KEY----- \ No newline at end of file From c4bc00d2e6d227c98ada146fe69da2b3a745292e Mon Sep 17 00:00:00 2001 From: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Date: Thu, 29 Oct 2020 10:38:17 -0700 Subject: [PATCH 10/17] Update google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java Co-authored-by: Jeff Ching --- .../com/google/api/client/http/javanet/NetHttpTransport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index 4601d97f0..56156ea5e 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -303,7 +303,7 @@ public Builder trustCertificates(KeyStore trustStore) throws GeneralSecurityExce * @param mtlsKeystorePassword password for mtlsKeyStore parameter */ public Builder trustCertificates( - KeyStore trustStore, KeyStore mtlsKeyStore, String mtlsKeystorePassword) + KeyStore trustStore, KeyStore mtlsKeyStore, String mtlsKeyStorePassword) throws GeneralSecurityException { if (mtlsKeyStore != null && mtlsKeyStore.size() > 0) { this.isMtls = true; From a97ea3d8ae9cda41bbae6a37cb808ca46a0355f3 Mon Sep 17 00:00:00 2001 From: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Date: Thu, 29 Oct 2020 10:38:28 -0700 Subject: [PATCH 11/17] Update google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java Co-authored-by: Jeff Ching --- .../com/google/api/client/http/javanet/NetHttpTransport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index 56156ea5e..974203e5b 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -314,7 +314,7 @@ public Builder trustCertificates( trustStore, SslUtils.getPkixTrustManagerFactory(), mtlsKeyStore, - mtlsKeystorePassword, + mtlsKeyStorePassword, SslUtils.getDefaultKeyManagerFactory()); return setSslSocketFactory(sslContext.getSocketFactory()); } From 74694670a48e87d636c3d63178a8be1b9b83c0af Mon Sep 17 00:00:00 2001 From: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Date: Thu, 29 Oct 2020 10:38:40 -0700 Subject: [PATCH 12/17] Update google-http-client/src/main/java/com/google/api/client/util/SslUtils.java Co-authored-by: Jeff Ching --- .../src/main/java/com/google/api/client/util/SslUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java index f4c2e3a4b..190e9bdde 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java @@ -120,7 +120,7 @@ public static SSLContext initSslContext( * @param trustManagerFactory trust manager factory (for example {@link * #getPkixTrustManagerFactory()}) * @param mtlsKeyStore key store for client certificate and key to establish mutual TLS - * @param mtlsKeystorePassword password for mtlsKeyStore parameter + * @param mtlsKeyStorePassword password for mtlsKeyStore parameter * @param keyManagerFactory key manager factory (for example {@link * #getDefaultKeyManagerFactory()}) */ From a61ed1a5934276f376924ab0f108536422e7be1d Mon Sep 17 00:00:00 2001 From: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Date: Thu, 29 Oct 2020 10:38:54 -0700 Subject: [PATCH 13/17] Update google-http-client/src/main/java/com/google/api/client/util/SslUtils.java Co-authored-by: Jeff Ching --- .../src/main/java/com/google/api/client/util/SslUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java index 190e9bdde..c6409b5d4 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java @@ -129,7 +129,7 @@ public static SSLContext initSslContext( KeyStore trustStore, TrustManagerFactory trustManagerFactory, KeyStore mtlsKeyStore, - String mtlsKeystorePassword, + String mtlsKeyStorePassword, KeyManagerFactory keyManagerFactory) throws GeneralSecurityException { trustManagerFactory.init(trustStore); From 93c3452bfc16a9b6e1f373d13fb589c9b3530424 Mon Sep 17 00:00:00 2001 From: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Date: Thu, 29 Oct 2020 10:39:07 -0700 Subject: [PATCH 14/17] Update google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java Co-authored-by: Jeff Ching --- .../test/java/com/google/api/client/util/SecurityUtilsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java index 10b7bb612..faa8a0ee3 100644 --- a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java +++ b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java @@ -211,6 +211,6 @@ public void testCreateMtlsKeyStoreSuccess() throws Exception { KeyStore mtlsKeyStore = SecurityUtils.createMtlsKeyStore(certAndKey); - assertEquals(mtlsKeyStore.size(), 1); + assertEquals(1, mtlsKeyStore.size()); } } From d195f6555479e665ae21754ca5f9a1d347849ce6 Mon Sep 17 00:00:00 2001 From: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Date: Thu, 29 Oct 2020 10:39:24 -0700 Subject: [PATCH 15/17] Update google-http-client/src/main/java/com/google/api/client/util/SslUtils.java Co-authored-by: Jeff Ching --- .../src/main/java/com/google/api/client/util/SslUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java index c6409b5d4..fc4b7900b 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SslUtils.java @@ -133,7 +133,7 @@ public static SSLContext initSslContext( KeyManagerFactory keyManagerFactory) throws GeneralSecurityException { trustManagerFactory.init(trustStore); - keyManagerFactory.init(mtlsKeyStore, mtlsKeystorePassword.toCharArray()); + keyManagerFactory.init(mtlsKeyStore, mtlsKeyStorePassword.toCharArray()); sslContext.init( keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); return sslContext; From 13d7d19e9892349464682667bec9be9250f24d0e Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Thu, 29 Oct 2020 10:53:22 -0700 Subject: [PATCH 16/17] update the code --- .../client/http/javanet/NetHttpTransport.java | 3 +- .../google/api/client/util/SecurityUtils.java | 2 +- .../api/client/util/SecurityUtilsTest.java | 48 ++++++++----------- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index 974203e5b..dfe5bf3db 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -299,7 +299,8 @@ public Builder trustCertificates(KeyStore trustStore) throws GeneralSecurityExce * * @param trustStore certificate trust store (use for example {@link SecurityUtils#loadKeyStore} * or {@link SecurityUtils#loadKeyStoreFromCertificates}) - * @param mtlsKeyStore key store for client certificate and key to establish mutual TLS. + * @param mtlsKeyStore key store for client certificate and key to establish mutual TLS. (use + * for example {@link SecurityUtils#createMtlsKeyStore(InputStream)}) * @param mtlsKeystorePassword password for mtlsKeyStore parameter */ public Builder trustCertificates( diff --git a/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java b/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java index 953fc9366..8f59a8747 100644 --- a/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java +++ b/google-http-client/src/main/java/com/google/api/client/util/SecurityUtils.java @@ -284,7 +284,7 @@ public static KeyStore createMtlsKeyStore(InputStream certAndKey) break; } - if ("CERTIFICATE".equals(section.getTitle())) { + if (certSection == null && "CERTIFICATE".equals(section.getTitle())) { certSection = section; } else if ("PRIVATE KEY".equals(section.getTitle())) { keySection = section; diff --git a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java index faa8a0ee3..21bdd9dc3 100644 --- a/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java +++ b/google-http-client/src/test/java/com/google/api/client/util/SecurityUtilsTest.java @@ -14,9 +14,6 @@ package com.google.api.client.util; -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertThrows; - import com.google.api.client.testing.json.webtoken.TestCertificates; import com.google.api.client.testing.util.SecurityTestUtils; import java.io.ByteArrayInputStream; @@ -30,7 +27,6 @@ import javax.net.ssl.X509TrustManager; import junit.framework.TestCase; import org.junit.Assert; -import org.junit.function.ThrowingRunnable; /** * Tests {@link SecurityUtils}. @@ -172,35 +168,31 @@ public void testCreateMtlsKeyStoreNoCert() throws Exception { getClass() .getClassLoader() .getResourceAsStream("com/google/api/client/util/privateKey.pem"); - IllegalArgumentException exception = - assertThrows( - IllegalArgumentException.class, - new ThrowingRunnable() { - @Override - public void run() throws Throwable { - SecurityUtils.createMtlsKeyStore(certMissing); - } - }); - assertThat(exception) - .hasMessageThat() - .isEqualTo("certificate is missing from certAndKey string"); + + boolean thrown = false; + try { + SecurityUtils.createMtlsKeyStore(certMissing); + fail("should have thrown"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("certificate is missing from certAndKey string")); + thrown = true; + } + assertTrue("should have caught an IllegalArgumentException", thrown); } public void testCreateMtlsKeyStoreNoPrivateKey() throws Exception { final InputStream privateKeyMissing = getClass().getClassLoader().getResourceAsStream("com/google/api/client/util/cert.pem"); - IllegalArgumentException exception = - assertThrows( - IllegalArgumentException.class, - new ThrowingRunnable() { - @Override - public void run() throws Throwable { - SecurityUtils.createMtlsKeyStore(privateKeyMissing); - } - }); - assertThat(exception) - .hasMessageThat() - .isEqualTo("private key is missing from certAndKey string"); + + boolean thrown = false; + try { + SecurityUtils.createMtlsKeyStore(privateKeyMissing); + fail("should have thrown"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("private key is missing from certAndKey string")); + thrown = true; + } + assertTrue("should have caught an IllegalArgumentException", thrown); } public void testCreateMtlsKeyStoreSuccess() throws Exception { From bade79a0a0ff90bccc47bc80dce115f606e4cb33 Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Thu, 29 Oct 2020 11:08:10 -0700 Subject: [PATCH 17/17] fix name --- .../com/google/api/client/http/javanet/NetHttpTransport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java index dfe5bf3db..b44b36a62 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java +++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpTransport.java @@ -301,7 +301,7 @@ public Builder trustCertificates(KeyStore trustStore) throws GeneralSecurityExce * or {@link SecurityUtils#loadKeyStoreFromCertificates}) * @param mtlsKeyStore key store for client certificate and key to establish mutual TLS. (use * for example {@link SecurityUtils#createMtlsKeyStore(InputStream)}) - * @param mtlsKeystorePassword password for mtlsKeyStore parameter + * @param mtlsKeyStorePassword password for mtlsKeyStore parameter */ public Builder trustCertificates( KeyStore trustStore, KeyStore mtlsKeyStore, String mtlsKeyStorePassword)