Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add mtls support for NetHttpTransport #1147

Merged
merged 17 commits into from Oct 30, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -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;
}
arithmetic1728 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Builds a low level HTTP request for the given HTTP method.
*
Expand Down
Expand Up @@ -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.
*
* <p>Instead use {@link Builder} to modify behavior.
*/
public NetHttpTransport() {
this((ConnectionFactory) null, null, null);
this((ConnectionFactory) null, null, null, false);
}

/**
Expand All @@ -104,26 +107,33 @@ public NetHttpTransport() {
* system properties</a>
* @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);
}

/**
* @param connectionFactory factory to produce connections from {@link URL}s; if {@code null} then
* {@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) {
Expand All @@ -141,6 +151,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);
Expand Down Expand Up @@ -189,6 +204,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 <a
* href="http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html">system
Expand Down Expand Up @@ -275,6 +293,32 @@ 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}
arithmetic1728 marked this conversation as resolved.
Show resolved Hide resolved
* or {@link SecurityUtils#loadKeyStoreFromCertificates})
* @param keyStore key store for client certificate and key
* @param keystorePassword password for keyStore parameter
*/
public Builder trustCertificates(
arithmetic1728 marked this conversation as resolved.
Show resolved Hide resolved
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} <br>
* Disables validating server SSL certificates by setting the SSL socket factory using {@link
Expand Down Expand Up @@ -319,8 +363,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);
}
}
}
Expand Up @@ -109,6 +109,36 @@ 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,
arithmetic1728 marked this conversation as resolved.
Show resolved Hide resolved
KeyManagerFactory keyManagerFactory)
throws GeneralSecurityException {
trustManagerFactory.init(trustStore);
keyManagerFactory.init(keyStore, keystorePassword);
sslContext.init(
keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
return sslContext;
}

/**
* {@link Beta} <br>
* Returns an SSL context in which all X.509 certificates are trusted.
Expand Down