Skip to content

Commit 1d8304c

Browse files
feat: add mtls support to GoogleNetHttpTransport and GoogleApacheHttpTransport (#1619)
1 parent 5f9780a commit 1d8304c

File tree

14 files changed

+775
-45
lines changed

14 files changed

+775
-45
lines changed

google-api-client/src/main/java/com/google/api/client/googleapis/apache/v2/GoogleApacheHttpTransport.java

+59-19
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
package com.google.api.client.googleapis.apache.v2;
1616

1717
import com.google.api.client.googleapis.GoogleUtils;
18+
import com.google.api.client.googleapis.mtls.MtlsProvider;
19+
import com.google.api.client.googleapis.mtls.MtlsUtils;
20+
import com.google.api.client.googleapis.util.Utils;
1821
import com.google.api.client.http.apache.v2.ApacheHttpTransport;
22+
import com.google.api.client.util.Beta;
1923
import com.google.api.client.util.SslUtils;
2024
import java.io.IOException;
2125
import java.net.ProxySelector;
@@ -24,7 +28,6 @@
2428
import java.util.concurrent.TimeUnit;
2529
import javax.net.ssl.SSLContext;
2630
import org.apache.http.client.HttpClient;
27-
import org.apache.http.config.SocketConfig;
2831
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
2932
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
3033
import org.apache.http.impl.client.HttpClientBuilder;
@@ -39,11 +42,35 @@
3942
public final class GoogleApacheHttpTransport {
4043

4144
/**
42-
* Returns a new instance of {@link ApacheHttpTransport} that uses
43-
* {@link GoogleUtils#getCertificateTrustStore()} for the trusted certificates.
45+
* Returns a new instance of {@link ApacheHttpTransport} that uses {@link
46+
* GoogleUtils#getCertificateTrustStore()} for the trusted certificates. If
47+
* `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true", and the default
48+
* client certificate key store from {@link Utils#loadDefaultMtlsKeyStore()} is not null, then the
49+
* transport uses the default client certificate and is mutual TLS.
4450
*/
45-
public static ApacheHttpTransport newTrustedTransport() throws GeneralSecurityException,
46-
IOException {
51+
public static ApacheHttpTransport newTrustedTransport()
52+
throws GeneralSecurityException, IOException {
53+
return newTrustedTransport(MtlsUtils.getDefaultMtlsProvider());
54+
}
55+
56+
/**
57+
* {@link Beta} <br>
58+
* Returns a new instance of {@link ApacheHttpTransport} that uses {@link
59+
* GoogleUtils#getCertificateTrustStore()} for the trusted certificates. mtlsProvider can be used
60+
* to configure mutual TLS for the transport.
61+
*
62+
* @param mtlsProvider MtlsProvider to configure mutual TLS for the transport
63+
*/
64+
@Beta
65+
public static ApacheHttpTransport newTrustedTransport(MtlsProvider mtlsProvider)
66+
throws GeneralSecurityException, IOException {
67+
KeyStore mtlsKeyStore = null;
68+
String mtlsKeyStorePassword = null;
69+
if (mtlsProvider.useMtlsClientCertificate()) {
70+
mtlsKeyStore = mtlsProvider.getKeyStore();
71+
mtlsKeyStorePassword = mtlsProvider.getKeyStorePassword();
72+
}
73+
4774
PoolingHttpClientConnectionManager connectionManager =
4875
new PoolingHttpClientConnectionManager(-1, TimeUnit.MILLISECONDS);
4976

@@ -53,22 +80,35 @@ public static ApacheHttpTransport newTrustedTransport() throws GeneralSecurityEx
5380
// Use the included trust store
5481
KeyStore trustStore = GoogleUtils.getCertificateTrustStore();
5582
SSLContext sslContext = SslUtils.getTlsSslContext();
56-
SslUtils.initSslContext(sslContext, trustStore, SslUtils.getPkixTrustManagerFactory());
83+
84+
boolean isMtls = false;
85+
if (mtlsKeyStore != null && mtlsKeyStorePassword != null) {
86+
isMtls = true;
87+
SslUtils.initSslContext(
88+
sslContext,
89+
trustStore,
90+
SslUtils.getPkixTrustManagerFactory(),
91+
mtlsKeyStore,
92+
mtlsKeyStorePassword,
93+
SslUtils.getDefaultKeyManagerFactory());
94+
} else {
95+
SslUtils.initSslContext(sslContext, trustStore, SslUtils.getPkixTrustManagerFactory());
96+
}
5797
LayeredConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
5898

59-
HttpClient client = HttpClientBuilder.create()
60-
.useSystemProperties()
61-
.setSSLSocketFactory(socketFactory)
62-
.setMaxConnTotal(200)
63-
.setMaxConnPerRoute(20)
64-
.setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault()))
65-
.setConnectionManager(connectionManager)
66-
.disableRedirectHandling()
67-
.disableAutomaticRetries()
68-
.build();
69-
return new ApacheHttpTransport(client);
99+
HttpClient client =
100+
HttpClientBuilder.create()
101+
.useSystemProperties()
102+
.setSSLSocketFactory(socketFactory)
103+
.setMaxConnTotal(200)
104+
.setMaxConnPerRoute(20)
105+
.setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault()))
106+
.setConnectionManager(connectionManager)
107+
.disableRedirectHandling()
108+
.disableAutomaticRetries()
109+
.build();
110+
return new ApacheHttpTransport(client, isMtls);
70111
}
71112

72-
private GoogleApacheHttpTransport() {
73-
}
113+
private GoogleApacheHttpTransport() {}
74114
}

google-api-client/src/main/java/com/google/api/client/googleapis/javanet/GoogleNetHttpTransport.java

+50-18
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
package com.google.api.client.googleapis.javanet;
1616

1717
import com.google.api.client.googleapis.GoogleUtils;
18+
import com.google.api.client.googleapis.mtls.MtlsProvider;
19+
import com.google.api.client.googleapis.mtls.MtlsUtils;
20+
import com.google.api.client.googleapis.util.Utils;
1821
import com.google.api.client.http.javanet.NetHttpTransport;
22+
import com.google.api.client.util.Beta;
1923
import java.io.IOException;
2024
import java.security.GeneralSecurityException;
2125
import java.security.KeyStore;
@@ -29,32 +33,60 @@
2933
public class GoogleNetHttpTransport {
3034

3135
/**
32-
* Returns a new instance of {@link NetHttpTransport} that uses
33-
* {@link GoogleUtils#getCertificateTrustStore()} for the trusted certificates using
34-
* {@link com.google.api.client.http.javanet.NetHttpTransport.Builder#trustCertificates(KeyStore)}
35-
* .
36+
* Returns a new instance of {@link NetHttpTransport} that uses {@link
37+
* GoogleUtils#getCertificateTrustStore()} for the trusted certificates using {@link
38+
* com.google.api.client.http.javanet.NetHttpTransport.Builder#trustCertificates(KeyStore)}. If
39+
* `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true", and the default
40+
* client certificate key store from {@link Utils#loadDefaultMtlsKeyStore()} is not null, then the
41+
* transport uses the default client certificate and is mutual TLS.
3642
*
37-
* <p>
38-
* This helper method doesn't provide for customization of the {@link NetHttpTransport}, such as
39-
* the ability to specify a proxy. To do use, use
40-
* {@link com.google.api.client.http.javanet.NetHttpTransport.Builder}, for example:
41-
* </p>
43+
* <p>This helper method doesn't provide for customization of the {@link NetHttpTransport}, such
44+
* as the ability to specify a proxy. To do use, use {@link
45+
* com.google.api.client.http.javanet.NetHttpTransport.Builder}, for example:
4246
*
4347
* <pre>
44-
static HttpTransport newProxyTransport() throws GeneralSecurityException, IOException {
45-
NetHttpTransport.Builder builder = new NetHttpTransport.Builder();
46-
builder.trustCertificates(GoogleUtils.getCertificateTrustStore());
47-
builder.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 3128)));
48-
return builder.build();
49-
}
48+
* static HttpTransport newProxyTransport() throws GeneralSecurityException, IOException {
49+
* NetHttpTransport.Builder builder = new NetHttpTransport.Builder();
50+
* builder.trustCertificates(GoogleUtils.getCertificateTrustStore());
51+
* builder.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 3128)));
52+
* return builder.build();
53+
* }
5054
* </pre>
5155
*/
5256
public static NetHttpTransport newTrustedTransport()
5357
throws GeneralSecurityException, IOException {
54-
return new NetHttpTransport.Builder().trustCertificates(GoogleUtils.getCertificateTrustStore())
55-
.build();
58+
return newTrustedTransport(MtlsUtils.getDefaultMtlsProvider());
5659
}
5760

58-
private GoogleNetHttpTransport() {
61+
/**
62+
* {@link Beta} <br>
63+
* Returns a new instance of {@link NetHttpTransport} that uses {@link
64+
* GoogleUtils#getCertificateTrustStore()} for the trusted certificates using {@link
65+
* com.google.api.client.http.javanet.NetHttpTransport.Builder#trustCertificates(KeyStore)}.
66+
* mtlsProvider can be used to configure mutual TLS for the transport.
67+
*
68+
* @param mtlsProvider MtlsProvider to configure mutual TLS for the transport
69+
*/
70+
@Beta
71+
public static NetHttpTransport newTrustedTransport(MtlsProvider mtlsProvider)
72+
throws GeneralSecurityException, IOException {
73+
KeyStore mtlsKeyStore = null;
74+
String mtlsKeyStorePassword = null;
75+
if (mtlsProvider.useMtlsClientCertificate()) {
76+
mtlsKeyStore = mtlsProvider.getKeyStore();
77+
mtlsKeyStorePassword = mtlsProvider.getKeyStorePassword();
78+
}
79+
80+
if (mtlsKeyStore != null && mtlsKeyStorePassword != null) {
81+
return new NetHttpTransport.Builder()
82+
.trustCertificates(
83+
GoogleUtils.getCertificateTrustStore(), mtlsKeyStore, mtlsKeyStorePassword)
84+
.build();
85+
}
86+
return new NetHttpTransport.Builder()
87+
.trustCertificates(GoogleUtils.getCertificateTrustStore())
88+
.build();
5989
}
90+
91+
private GoogleNetHttpTransport() {}
6092
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package com.google.api.client.googleapis.mtls;
16+
17+
import java.util.List;
18+
19+
import com.google.api.client.json.GenericJson;
20+
import com.google.api.client.util.Beta;
21+
import com.google.api.client.util.Key;
22+
23+
/**
24+
* {@link Beta} <br>
25+
* Data class representing context_aware_metadata.json file.
26+
*
27+
* @since 1.31
28+
*/
29+
@Beta
30+
public class ContextAwareMetadataJson extends GenericJson {
31+
/** Cert provider command */
32+
@Key("cert_provider_command")
33+
private List<String> commands;
34+
35+
/**
36+
* Returns the cert provider command.
37+
*
38+
* @since 1.31
39+
*/
40+
public final List<String> getCommands() {
41+
return commands;
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package com.google.api.client.googleapis.mtls;
16+
17+
import com.google.api.client.util.Beta;
18+
import java.io.IOException;
19+
import java.security.GeneralSecurityException;
20+
import java.security.KeyStore;
21+
22+
/**
23+
* {@link Beta} <br>
24+
* Provider interface for mutual TLS. It is used in {@link
25+
* GoogleApacheHttpTransport#newTrustedTransport(MtlsProvider)} and {@link
26+
* GoogleNetHttpTransport#newTrustedTransport(MtlsProvider)} to configure the mutual TLS in the
27+
* transport.
28+
*
29+
* @since 1.31
30+
*/
31+
@Beta
32+
public interface MtlsProvider {
33+
/**
34+
* Returns if mutual TLS client certificate should be used. If the value is true, the key store
35+
* from {@link #getKeyStore()} and key store password from {@link #getKeyStorePassword()} will be
36+
* used to configure mutual TLS transport.
37+
*/
38+
boolean useMtlsClientCertificate();
39+
40+
/** The key store to use for mutual TLS. */
41+
String getKeyStorePassword();
42+
43+
/** The password for mutual TLS key store. */
44+
KeyStore getKeyStore() throws IOException, GeneralSecurityException;
45+
}

0 commit comments

Comments
 (0)