Skip to content
Permalink
Browse files
feat: add mtls support to GoogleNetHttpTransport and GoogleApacheHttp…
…Transport (#1619)
  • Loading branch information
arithmetic1728 committed Nov 10, 2020
1 parent 5f9780a commit 1d8304c6311e910293b800ffdbf0bb6f19cf7fff
Showing with 775 additions and 45 deletions.
  1. +59 −19 ...pi-client/src/main/java/com/google/api/client/googleapis/apache/v2/GoogleApacheHttpTransport.java
  2. +50 −18 google-api-client/src/main/java/com/google/api/client/googleapis/javanet/GoogleNetHttpTransport.java
  3. +43 −0 google-api-client/src/main/java/com/google/api/client/googleapis/mtls/ContextAwareMetadataJson.java
  4. +45 −0 google-api-client/src/main/java/com/google/api/client/googleapis/mtls/MtlsProvider.java
  5. +155 −0 google-api-client/src/main/java/com/google/api/client/googleapis/mtls/MtlsUtils.java
  6. +20 −0 google-api-client/src/main/java/com/google/api/client/googleapis/mtls/package-info.java
  7. +3 −8 google-api-client/src/main/java/com/google/api/client/googleapis/util/Utils.java
  8. +29 −0 ...lient/src/test/java/com/google/api/client/googleapis/apache/v2/GoogleApacheHttpTransportTest.java
  9. +29 −0 ...api-client/src/test/java/com/google/api/client/googleapis/javanet/GoogleNetHttpTransportTest.java
  10. +112 −0 google-api-client/src/test/java/com/google/api/client/googleapis/mtls/MtlsTransportBaseTest.java
  11. +182 −0 google-api-client/src/test/java/com/google/api/client/googleapis/mtls/MtlsUtilsTest.java
  12. +30 −0 google-api-client/src/test/resources/com/google/api/client/googleapis/util/mtlsCertAndKey.pem
  13. +9 −0 ...-client/src/test/resources/com/google/api/client/googleapis/util/mtls_context_aware_metadata.json
  14. +9 −0 ...test/resources/com/google/api/client/googleapis/util/mtls_context_aware_metadata_bad_command.json
@@ -15,7 +15,11 @@
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;
import java.io.IOException;
import java.net.ProxySelector;
@@ -24,7 +28,6 @@
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import org.apache.http.client.HttpClient;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
@@ -39,11 +42,35 @@
public final class GoogleApacheHttpTransport {

/**
* Returns a new instance of {@link ApacheHttpTransport} that uses
* {@link GoogleUtils#getCertificateTrustStore()} for the trusted certificates.
* 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.
*/
public static ApacheHttpTransport newTrustedTransport() throws GeneralSecurityException,
IOException {
public static ApacheHttpTransport newTrustedTransport()
throws GeneralSecurityException, IOException {
return newTrustedTransport(MtlsUtils.getDefaultMtlsProvider());
}

/**
* {@link Beta} <br>
* 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.
*
* @param mtlsProvider MtlsProvider to configure mutual TLS for the transport
*/
@Beta
public static ApacheHttpTransport newTrustedTransport(MtlsProvider mtlsProvider)
throws GeneralSecurityException, IOException {
KeyStore mtlsKeyStore = null;
String mtlsKeyStorePassword = null;
if (mtlsProvider.useMtlsClientCertificate()) {
mtlsKeyStore = mtlsProvider.getKeyStore();
mtlsKeyStorePassword = mtlsProvider.getKeyStorePassword();
}

PoolingHttpClientConnectionManager connectionManager =
new PoolingHttpClientConnectionManager(-1, TimeUnit.MILLISECONDS);

@@ -53,22 +80,35 @@ public static ApacheHttpTransport newTrustedTransport() throws GeneralSecurityEx
// Use the included trust store
KeyStore trustStore = GoogleUtils.getCertificateTrustStore();
SSLContext sslContext = SslUtils.getTlsSslContext();
SslUtils.initSslContext(sslContext, trustStore, SslUtils.getPkixTrustManagerFactory());

boolean isMtls = false;
if (mtlsKeyStore != null && mtlsKeyStorePassword != null) {
isMtls = true;
SslUtils.initSslContext(
sslContext,
trustStore,
SslUtils.getPkixTrustManagerFactory(),
mtlsKeyStore,
mtlsKeyStorePassword,
SslUtils.getDefaultKeyManagerFactory());
} else {
SslUtils.initSslContext(sslContext, trustStore, SslUtils.getPkixTrustManagerFactory());
}
LayeredConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);

HttpClient client = HttpClientBuilder.create()
.useSystemProperties()
.setSSLSocketFactory(socketFactory)
.setMaxConnTotal(200)
.setMaxConnPerRoute(20)
.setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault()))
.setConnectionManager(connectionManager)
.disableRedirectHandling()
.disableAutomaticRetries()
.build();
return new ApacheHttpTransport(client);
HttpClient client =
HttpClientBuilder.create()
.useSystemProperties()
.setSSLSocketFactory(socketFactory)
.setMaxConnTotal(200)
.setMaxConnPerRoute(20)
.setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault()))
.setConnectionManager(connectionManager)
.disableRedirectHandling()
.disableAutomaticRetries()
.build();
return new ApacheHttpTransport(client, isMtls);
}

private GoogleApacheHttpTransport() {
}
private GoogleApacheHttpTransport() {}
}
@@ -15,7 +15,11 @@
package com.google.api.client.googleapis.javanet;

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.javanet.NetHttpTransport;
import com.google.api.client.util.Beta;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
@@ -29,32 +33,60 @@
public class GoogleNetHttpTransport {

/**
* Returns a new instance of {@link NetHttpTransport} that uses
* {@link GoogleUtils#getCertificateTrustStore()} for the trusted certificates using
* {@link com.google.api.client.http.javanet.NetHttpTransport.Builder#trustCertificates(KeyStore)}
* .
* Returns a new instance of {@link NetHttpTransport} that uses {@link
* GoogleUtils#getCertificateTrustStore()} for the trusted certificates using {@link
* com.google.api.client.http.javanet.NetHttpTransport.Builder#trustCertificates(KeyStore)}. 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.
*
* <p>
* This helper method doesn't provide for customization of the {@link NetHttpTransport}, such as
* the ability to specify a proxy. To do use, use
* {@link com.google.api.client.http.javanet.NetHttpTransport.Builder}, for example:
* </p>
* <p>This helper method doesn't provide for customization of the {@link NetHttpTransport}, such
* as the ability to specify a proxy. To do use, use {@link
* com.google.api.client.http.javanet.NetHttpTransport.Builder}, for example:
*
* <pre>
static HttpTransport newProxyTransport() throws GeneralSecurityException, IOException {
NetHttpTransport.Builder builder = new NetHttpTransport.Builder();
builder.trustCertificates(GoogleUtils.getCertificateTrustStore());
builder.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 3128)));
return builder.build();
}
* static HttpTransport newProxyTransport() throws GeneralSecurityException, IOException {
* NetHttpTransport.Builder builder = new NetHttpTransport.Builder();
* builder.trustCertificates(GoogleUtils.getCertificateTrustStore());
* builder.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 3128)));
* return builder.build();
* }
* </pre>
*/
public static NetHttpTransport newTrustedTransport()
throws GeneralSecurityException, IOException {
return new NetHttpTransport.Builder().trustCertificates(GoogleUtils.getCertificateTrustStore())
.build();
return newTrustedTransport(MtlsUtils.getDefaultMtlsProvider());
}

private GoogleNetHttpTransport() {
/**
* {@link Beta} <br>
* Returns a new instance of {@link NetHttpTransport} that uses {@link
* GoogleUtils#getCertificateTrustStore()} for the trusted certificates using {@link
* com.google.api.client.http.javanet.NetHttpTransport.Builder#trustCertificates(KeyStore)}.
* mtlsProvider can be used to configure mutual TLS for the transport.
*
* @param mtlsProvider MtlsProvider to configure mutual TLS for the transport
*/
@Beta
public static NetHttpTransport newTrustedTransport(MtlsProvider mtlsProvider)
throws GeneralSecurityException, IOException {
KeyStore mtlsKeyStore = null;
String mtlsKeyStorePassword = null;
if (mtlsProvider.useMtlsClientCertificate()) {
mtlsKeyStore = mtlsProvider.getKeyStore();
mtlsKeyStorePassword = mtlsProvider.getKeyStorePassword();
}

if (mtlsKeyStore != null && mtlsKeyStorePassword != null) {
return new NetHttpTransport.Builder()
.trustCertificates(
GoogleUtils.getCertificateTrustStore(), mtlsKeyStore, mtlsKeyStorePassword)
.build();
}
return new NetHttpTransport.Builder()
.trustCertificates(GoogleUtils.getCertificateTrustStore())
.build();
}

private GoogleNetHttpTransport() {}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2020 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.mtls;

import java.util.List;

import com.google.api.client.json.GenericJson;
import com.google.api.client.util.Beta;
import com.google.api.client.util.Key;

/**
* {@link Beta} <br>
* Data class representing context_aware_metadata.json file.
*
* @since 1.31
*/
@Beta
public class ContextAwareMetadataJson extends GenericJson {
/** Cert provider command */
@Key("cert_provider_command")
private List<String> commands;

/**
* Returns the cert provider command.
*
* @since 1.31
*/
public final List<String> getCommands() {
return commands;
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 2020 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.mtls;

import com.google.api.client.util.Beta;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;

/**
* {@link Beta} <br>
* Provider interface for mutual TLS. It is used in {@link
* GoogleApacheHttpTransport#newTrustedTransport(MtlsProvider)} and {@link
* GoogleNetHttpTransport#newTrustedTransport(MtlsProvider)} to configure the mutual TLS in the
* transport.
*
* @since 1.31
*/
@Beta
public interface MtlsProvider {
/**
* Returns if mutual TLS client certificate should be used. If the value is true, the key store
* from {@link #getKeyStore()} and key store password from {@link #getKeyStorePassword()} will be
* used to configure mutual TLS transport.
*/
boolean useMtlsClientCertificate();

/** The key store to use for mutual TLS. */
String getKeyStorePassword();

/** The password for mutual TLS key store. */
KeyStore getKeyStore() throws IOException, GeneralSecurityException;
}

0 comments on commit 1d8304c

Please sign in to comment.