mirror of https://github.com/grpc/grpc-java.git
api: Add mTLS and Trust/KeyManager Credentials API
This commit is contained in:
parent
132a40a1cf
commit
d937ec5baf
|
|
@ -16,9 +16,19 @@
|
|||
|
||||
package io.grpc;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
/**
|
||||
* TLS credentials, providing server authentication and encryption. Consumers of this credential
|
||||
|
|
@ -34,9 +44,82 @@ public final class TlsChannelCredentials extends ChannelCredentials {
|
|||
}
|
||||
|
||||
private final boolean fakeFeature;
|
||||
private final byte[] certificateChain;
|
||||
private final byte[] privateKey;
|
||||
private final String privateKeyPassword;
|
||||
private final List<KeyManager> keyManagers;
|
||||
private final byte[] rootCertificates;
|
||||
private final List<TrustManager> trustManagers;
|
||||
|
||||
TlsChannelCredentials(Builder builder) {
|
||||
fakeFeature = builder.fakeFeature;
|
||||
certificateChain = builder.certificateChain;
|
||||
privateKey = builder.privateKey;
|
||||
privateKeyPassword = builder.privateKeyPassword;
|
||||
keyManagers = builder.keyManagers;
|
||||
rootCertificates = builder.rootCertificates;
|
||||
trustManagers = builder.trustManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* The certificate chain for the client's identity, as a new byte array. Generally should be
|
||||
* PEM-encoded. If {@code null}, some feature is providing key manager information via a different
|
||||
* method or no client identity is available.
|
||||
*/
|
||||
public byte[] getCertificateChain() {
|
||||
if (certificateChain == null) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.copyOf(certificateChain, certificateChain.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* The private key for the client's identity, as a new byte array. Generally should be in PKCS#8
|
||||
* format. If encrypted, {@link #getPrivateKeyPassword} is the decryption key. If unencrypted, the
|
||||
* password will be {@code null}. If {@code null}, some feature is providing key manager
|
||||
* information via a different method or no client identity is available.
|
||||
*/
|
||||
public byte[] getPrivateKey() {
|
||||
if (privateKey == null) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.copyOf(privateKey, privateKey.length);
|
||||
}
|
||||
|
||||
/** Returns the password to decrypt the private key, or {@code null} if unencrypted. */
|
||||
public String getPrivateKeyPassword() {
|
||||
return privateKeyPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key manager list which provides the client's identity. Entries are scanned checking
|
||||
* for specific types, like {@link javax.net.ssl.X509KeyManager}. Only a single entry for a type
|
||||
* is used. Entries earlier in the list are higher priority. If {@code null}, key manager
|
||||
* information is provided via a different method or no client identity is available.
|
||||
*/
|
||||
public List<KeyManager> getKeyManagers() {
|
||||
return keyManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Root trust certificates for verifying the server's identity that override the system's
|
||||
* defaults. Generally PEM-encoded with multiple certificates concatenated.
|
||||
*/
|
||||
public byte[] getRootCertificates() {
|
||||
if (rootCertificates == null) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.copyOf(rootCertificates, rootCertificates.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the trust manager list which verifies the server's identity. Entries are scanned
|
||||
* checking for specific types, like {@link javax.net.ssl.X509TrustManager}. Only a single entry
|
||||
* for a type is used. Entries earlier in the list are higher priority. If {@code null}, trust
|
||||
* manager information is provided via the system's default or a different method.
|
||||
*/
|
||||
public List<TrustManager> getTrustManagers() {
|
||||
return trustManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,6 +154,12 @@ public final class TlsChannelCredentials extends ChannelCredentials {
|
|||
if (fakeFeature) {
|
||||
requiredFeature(understoodFeatures, incomprehensible, Feature.FAKE);
|
||||
}
|
||||
if (rootCertificates != null || privateKey != null || keyManagers != null) {
|
||||
requiredFeature(understoodFeatures, incomprehensible, Feature.MTLS);
|
||||
}
|
||||
if (keyManagers != null || trustManagers != null) {
|
||||
requiredFeature(understoodFeatures, incomprehensible, Feature.CUSTOM_MANAGERS);
|
||||
}
|
||||
return Collections.unmodifiableSet(incomprehensible);
|
||||
}
|
||||
|
||||
|
|
@ -95,6 +184,34 @@ public final class TlsChannelCredentials extends ChannelCredentials {
|
|||
* a call to {@link #incomprehensible incomprehensible()} is implemented properly.
|
||||
*/
|
||||
FAKE,
|
||||
/**
|
||||
* Client identity may be provided and server verification can be tuned. This feature requires
|
||||
* observing {@link #getCertificateChain}, {@link #getPrivateKey}, and {@link
|
||||
* #getPrivateKeyPassword} as well as {@link #getRootCertificates()}. The certificate chain and
|
||||
* private key are used to configure a key manager to provide the client's identity. If no
|
||||
* certificate chain and private key are provided the client will have no identity. The root
|
||||
* certificates are used to configure a trust manager for verifying the server's identity. If no
|
||||
* root certificates are provided the trust manager will default to the system's root
|
||||
* certificates.
|
||||
*/
|
||||
MTLS,
|
||||
/**
|
||||
* Key managers and trust managers may be specified as {@link KeyManager} and {@link
|
||||
* TrustManager} objects. This feature requires observing {@link #getKeyManagers()} and {@link
|
||||
* #getTrustManagers()}. Generally {@link #MTLS} should also be supported, as that is the more
|
||||
* common method of configuration. When a manager is non-{@code null}, then it is wholly
|
||||
* responsible for key or trust material and usage; there is no need to check other manager
|
||||
* sources like {@link #getCertificateChain()} or {@link #getPrivateKey()} (if {@code
|
||||
* KeyManager} is available), or {@link #getRootCertificates()} (if {@code TrustManager} is
|
||||
* available).
|
||||
*
|
||||
* <p>If other manager sources are available (e.g., {@code getPrivateKey() != null}), then they
|
||||
* may be alternative representations of the same configuration and the consumer is free to use
|
||||
* those alternative representations if it prefers. But before doing so it <em>must</em> first
|
||||
* check that it understands that alternative representation by using {@link #incomprehensible}
|
||||
* <em>without</em> the {@code CUSTOM_MANAGERS} feature.
|
||||
*/
|
||||
CUSTOM_MANAGERS,
|
||||
;
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +224,12 @@ public final class TlsChannelCredentials extends ChannelCredentials {
|
|||
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7479")
|
||||
public static final class Builder {
|
||||
private boolean fakeFeature;
|
||||
private byte[] certificateChain;
|
||||
private byte[] privateKey;
|
||||
private String privateKeyPassword;
|
||||
private List<KeyManager> keyManagers;
|
||||
private byte[] rootCertificates;
|
||||
private List<TrustManager> trustManagers;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
|
|
@ -119,6 +242,126 @@ public final class TlsChannelCredentials extends ChannelCredentials {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the provided certificate chain and private key as the client's identity. Generally they
|
||||
* should be PEM-encoded and the key is an unencrypted PKCS#8 key (file headers have "BEGIN
|
||||
* CERTIFICATE" and "BEGIN PRIVATE KEY").
|
||||
*/
|
||||
public Builder keyManager(File certChain, File privateKey) throws IOException {
|
||||
return keyManager(certChain, privateKey, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the provided certificate chain and possibly-encrypted private key as the client's
|
||||
* identity. Generally they should be PEM-encoded and the key is a PKCS#8 key. If the private
|
||||
* key is unencrypted, then password must be {@code null}.
|
||||
*/
|
||||
public Builder keyManager(File certChain, File privateKey, String privateKeyPassword)
|
||||
throws IOException {
|
||||
InputStream certChainIs = new FileInputStream(certChain);
|
||||
try {
|
||||
InputStream privateKeyIs = new FileInputStream(privateKey);
|
||||
try {
|
||||
return keyManager(certChainIs, privateKeyIs, privateKeyPassword);
|
||||
} finally {
|
||||
privateKeyIs.close();
|
||||
}
|
||||
} finally {
|
||||
certChainIs.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the provided certificate chain and private key as the client's identity. Generally they
|
||||
* should be PEM-encoded and the key is an unencrypted PKCS#8 key (file headers have "BEGIN
|
||||
* CERTIFICATE" and "BEGIN PRIVATE KEY").
|
||||
*/
|
||||
public Builder keyManager(InputStream certChain, InputStream privateKey) throws IOException {
|
||||
return keyManager(certChain, privateKey, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the provided certificate chain and possibly-encrypted private key as the client's
|
||||
* identity. Generally they should be PEM-encoded and the key is a PKCS#8 key. If the private
|
||||
* key is unencrypted, then password must be {@code null}.
|
||||
*/
|
||||
public Builder keyManager(
|
||||
InputStream certChain, InputStream privateKey, String privateKeyPassword)
|
||||
throws IOException {
|
||||
byte[] certChainBytes = ByteStreams.toByteArray(certChain);
|
||||
byte[] privateKeyBytes = ByteStreams.toByteArray(privateKey);
|
||||
clearKeyManagers();
|
||||
this.certificateChain = certChainBytes;
|
||||
this.privateKey = privateKeyBytes;
|
||||
this.privateKeyPassword = privateKeyPassword;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the provided key manager select the client's identity. Although multiple are allowed,
|
||||
* only the first instance implementing a particular interface is used. So generally there will
|
||||
* just be a single entry and it implements {@link javax.net.ssl.X509KeyManager}.
|
||||
*/
|
||||
public Builder keyManager(KeyManager... keyManagers) {
|
||||
List<KeyManager> keyManagerList = Collections.unmodifiableList(new ArrayList<>(
|
||||
Arrays.asList(keyManagers)));
|
||||
clearKeyManagers();
|
||||
this.keyManagers = keyManagerList;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void clearKeyManagers() {
|
||||
this.certificateChain = null;
|
||||
this.privateKey = null;
|
||||
this.privateKeyPassword = null;
|
||||
this.keyManagers = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the provided root certificates to verify the server's identity instead of the system's
|
||||
* default. Generally they should be PEM-encoded with all the certificates concatenated together
|
||||
* (file header has "BEGIN CERTIFICATE", and would occur once per certificate).
|
||||
*/
|
||||
public Builder trustManager(File rootCerts) throws IOException {
|
||||
InputStream rootCertsIs = new FileInputStream(rootCerts);
|
||||
try {
|
||||
return trustManager(rootCertsIs);
|
||||
} finally {
|
||||
rootCertsIs.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the provided root certificates to verify the server's identity instead of the system's
|
||||
* default. Generally they should be PEM-encoded with all the certificates concatenated together
|
||||
* (file header has "BEGIN CERTIFICATE", and would occur once per certificate).
|
||||
*/
|
||||
public Builder trustManager(InputStream rootCerts) throws IOException {
|
||||
byte[] rootCertsBytes = ByteStreams.toByteArray(rootCerts);
|
||||
clearTrustManagers();
|
||||
this.rootCertificates = rootCertsBytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the provided trust manager verify the server's identity instead of the system's default.
|
||||
* Although multiple are allowed, only the first instance implementing a particular interface is
|
||||
* used. So generally there will just be a single entry and it implements {@link
|
||||
* javax.net.ssl.X509TrustManager}.
|
||||
*/
|
||||
public Builder trustManager(TrustManager... trustManagers) {
|
||||
List<TrustManager> trustManagerList = Collections.unmodifiableList(new ArrayList<>(
|
||||
Arrays.asList(trustManagers)));
|
||||
clearTrustManagers();
|
||||
this.trustManagers = trustManagerList;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void clearTrustManagers() {
|
||||
this.rootCertificates = null;
|
||||
this.trustManagers = null;
|
||||
}
|
||||
|
||||
/** Construct the credentials. */
|
||||
public ChannelCredentials build() {
|
||||
return new TlsChannelCredentials(this);
|
||||
|
|
|
|||
|
|
@ -16,15 +16,20 @@
|
|||
|
||||
package io.grpc;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
/**
|
||||
* TLS credentials, providing server identity and encryption. Consumers of this credential must
|
||||
|
|
@ -59,27 +64,44 @@ public final class TlsServerCredentials extends ServerCredentials {
|
|||
private final byte[] certificateChain;
|
||||
private final byte[] privateKey;
|
||||
private final String privateKeyPassword;
|
||||
private final List<KeyManager> keyManagers;
|
||||
private final ClientAuth clientAuth;
|
||||
private final byte[] rootCertificates;
|
||||
private final List<TrustManager> trustManagers;
|
||||
|
||||
TlsServerCredentials(Builder builder) {
|
||||
fakeFeature = builder.fakeFeature;
|
||||
certificateChain = builder.certificateChain;
|
||||
privateKey = builder.privateKey;
|
||||
privateKeyPassword = builder.privateKeyPassword;
|
||||
keyManagers = builder.keyManagers;
|
||||
clientAuth = builder.clientAuth;
|
||||
rootCertificates = builder.rootCertificates;
|
||||
trustManagers = builder.trustManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* The certificate chain, as a new byte array. Generally should be PEM-encoded.
|
||||
* The certificate chain for the server's identity, as a new byte array. Generally should be
|
||||
* PEM-encoded. If {@code null}, some feature is providing key manager information via a different
|
||||
* method.
|
||||
*/
|
||||
public byte[] getCertificateChain() {
|
||||
if (certificateChain == null) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.copyOf(certificateChain, certificateChain.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* The private key, as a new byte array. Generally should be in PKCS#8 format. If encrypted,
|
||||
* {@link #getPrivateKeyPassword} is the decryption key. If unencrypted, the password will be
|
||||
* {@code null}.
|
||||
* The private key for the server's identity, as a new byte array. Generally should be in PKCS#8
|
||||
* format. If encrypted, {@link #getPrivateKeyPassword} is the decryption key. If unencrypted, the
|
||||
* password will be {@code null}. If {@code null}, some feature is providing key manager
|
||||
* information via a different method.
|
||||
*/
|
||||
public byte[] getPrivateKey() {
|
||||
if (privateKey == null) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.copyOf(privateKey, privateKey.length);
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +110,42 @@ public final class TlsServerCredentials extends ServerCredentials {
|
|||
return privateKeyPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key manager list which provides the server's identity. Entries are scanned checking
|
||||
* for specific types, like {@link javax.net.ssl.X509KeyManager}. Only a single entry for a type
|
||||
* is used. Entries earlier in the list are higher priority. If {@code null}, key manager
|
||||
* information is provided via a different method.
|
||||
*/
|
||||
public List<KeyManager> getKeyManagers() {
|
||||
return keyManagers;
|
||||
}
|
||||
|
||||
/** Non-{@code null} setting indicating whether the server should expect a client's identity. */
|
||||
public ClientAuth getClientAuth() {
|
||||
return clientAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Root trust certificates for verifying the client's identity that override the system's
|
||||
* defaults. Generally PEM-encoded with multiple certificates concatenated.
|
||||
*/
|
||||
public byte[] getRootCertificates() {
|
||||
if (rootCertificates == null) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.copyOf(rootCertificates, rootCertificates.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the trust manager list which verifies the client's identity. Entries are scanned
|
||||
* checking for specific types, like {@link javax.net.ssl.X509TrustManager}. Only a single entry
|
||||
* for a type is used. Entries earlier in the list are higher priority. If {@code null}, trust
|
||||
* manager information is provided via the system's default or a different method.
|
||||
*/
|
||||
public List<TrustManager> getTrustManagers() {
|
||||
return trustManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty set if this credential can be adequately understood via
|
||||
* the features listed, otherwise returns a hint of features that are lacking
|
||||
|
|
@ -120,6 +178,12 @@ public final class TlsServerCredentials extends ServerCredentials {
|
|||
if (fakeFeature) {
|
||||
requiredFeature(understoodFeatures, incomprehensible, Feature.FAKE);
|
||||
}
|
||||
if (clientAuth != ClientAuth.NONE) {
|
||||
requiredFeature(understoodFeatures, incomprehensible, Feature.MTLS);
|
||||
}
|
||||
if (keyManagers != null || trustManagers != null) {
|
||||
requiredFeature(understoodFeatures, incomprehensible, Feature.CUSTOM_MANAGERS);
|
||||
}
|
||||
return Collections.unmodifiableSet(incomprehensible);
|
||||
}
|
||||
|
||||
|
|
@ -139,10 +203,37 @@ public final class TlsServerCredentials extends ServerCredentials {
|
|||
* a call to {@link #incomprehensible incomprehensible()} is implemented properly.
|
||||
*/
|
||||
FAKE,
|
||||
/**
|
||||
* Client certificates may be requested and verified. This feature requires observing {@link
|
||||
* #getRootCertificates()} and {@link #getClientAuth()}. The root certificates are used to
|
||||
* configure a trust manager for verifying the client's identity. If no root certificates are
|
||||
* provided the trust manager will default to the system's root certificates.
|
||||
*/
|
||||
MTLS,
|
||||
/**
|
||||
* Key managers and trust managers may be specified as {@link KeyManager} and {@link
|
||||
* TrustManager} objects. This feature by itself only implies {@link #getKeyManagers()} needs to
|
||||
* be observed. But along with {@link #MTLS}, then {@link #getTrustManagers()} needs to be
|
||||
* observed as well. When a manager is non-{@code null}, then it is wholly responsible for key
|
||||
* or trust material and usage; there is no need to check other manager sources like {@link
|
||||
* #getCertificateChain()} or {@link #getPrivateKey()} (if {@code KeyManager} is available), or
|
||||
* {@link #getRootCertificates()} (if {@code TrustManager} is available).
|
||||
*
|
||||
* <p>If other manager sources are available (e.g., {@code getPrivateKey() != null}), then they
|
||||
* may be alternative representations of the same configuration and the consumer is free to use
|
||||
* those alternative representations if it prefers. But before doing so it <em>must</em> first
|
||||
* check that it understands that alternative representation by using {@link #incomprehensible}
|
||||
* <em>without</em> the {@code CUSTOM_MANAGERS} feature.
|
||||
*/
|
||||
CUSTOM_MANAGERS,
|
||||
;
|
||||
}
|
||||
|
||||
/** Creates a builder for changing default configuration. */
|
||||
/**
|
||||
* Creates a builder for changing default configuration. There is no default key manager, so key
|
||||
* material must be specified. The default trust manager uses the system's root certificates. By
|
||||
* default no client authentication will occur.
|
||||
*/
|
||||
public static Builder newBuilder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
|
@ -154,6 +245,10 @@ public final class TlsServerCredentials extends ServerCredentials {
|
|||
private byte[] certificateChain;
|
||||
private byte[] privateKey;
|
||||
private String privateKeyPassword;
|
||||
private List<KeyManager> keyManagers;
|
||||
private ClientAuth clientAuth = ClientAuth.NONE;
|
||||
private byte[] rootCertificates;
|
||||
private List<TrustManager> trustManagers;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
|
|
@ -167,8 +262,8 @@ public final class TlsServerCredentials extends ServerCredentials {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates an instance using provided certificate chain and private key. Generally they should
|
||||
* be PEM-encoded and the key is an unencrypted PKCS#8 key (file headers have "BEGIN
|
||||
* Use the provided certificate chain and private key as the server's identity. Generally they
|
||||
* should be PEM-encoded and the key is an unencrypted PKCS#8 key (file headers have "BEGIN
|
||||
* CERTIFICATE" and "BEGIN PRIVATE KEY").
|
||||
*/
|
||||
public Builder keyManager(File certChain, File privateKey) throws IOException {
|
||||
|
|
@ -176,9 +271,9 @@ public final class TlsServerCredentials extends ServerCredentials {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates an instance using provided certificate chain and possibly-encrypted private key.
|
||||
* Generally they should be PEM-encoded and the key is a PKCS#8 key. If the private key is
|
||||
* unencrypted, then password must be {@code null}.
|
||||
* Use the provided certificate chain and possibly-encrypted private key as the server's
|
||||
* identity. Generally they should be PEM-encoded and the key is a PKCS#8 key. If the private
|
||||
* key is unencrypted, then password must be {@code null}.
|
||||
*/
|
||||
public Builder keyManager(File certChain, File privateKey, String privateKeyPassword)
|
||||
throws IOException {
|
||||
|
|
@ -196,8 +291,8 @@ public final class TlsServerCredentials extends ServerCredentials {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates an instance using provided certificate chain and private key. Generally they should
|
||||
* be PEM-encoded and the key is an unencrypted PKCS#8 key (file headers have "BEGIN
|
||||
* Use the provided certificate chain and private key as the server's identity. Generally they
|
||||
* should be PEM-encoded and the key is an unencrypted PKCS#8 key (file headers have "BEGIN
|
||||
* CERTIFICATE" and "BEGIN PRIVATE KEY").
|
||||
*/
|
||||
public Builder keyManager(InputStream certChain, InputStream privateKey) throws IOException {
|
||||
|
|
@ -205,27 +300,121 @@ public final class TlsServerCredentials extends ServerCredentials {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates an instance using provided certificate chain and possibly-encrypted private key.
|
||||
* Generally they should be PEM-encoded and the key is a PKCS#8 key. If the private key is
|
||||
* unencrypted, then password must be {@code null}.
|
||||
* Use the provided certificate chain and possibly-encrypted private key as the server's
|
||||
* identity. Generally they should be PEM-encoded and the key is a PKCS#8 key. If the private
|
||||
* key is unencrypted, then password must be {@code null}.
|
||||
*/
|
||||
public Builder keyManager(
|
||||
InputStream certChain, InputStream privateKey, String privateKeyPassword)
|
||||
throws IOException {
|
||||
byte[] certChainBytes = ByteStreams.toByteArray(certChain);
|
||||
byte[] privateKeyBytes = ByteStreams.toByteArray(privateKey);
|
||||
clearKeyManagers();
|
||||
this.certificateChain = certChainBytes;
|
||||
this.privateKey = privateKeyBytes;
|
||||
this.privateKeyPassword = privateKeyPassword;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the provided key manager select the server's identity. Although multiple are allowed,
|
||||
* only the first instance implementing a particular interface is used. So generally there will
|
||||
* just be a single entry and it implements {@link javax.net.ssl.X509KeyManager}.
|
||||
*/
|
||||
public Builder keyManager(KeyManager... keyManagers) {
|
||||
List<KeyManager> keyManagerList = Collections.unmodifiableList(new ArrayList<>(
|
||||
Arrays.asList(keyManagers)));
|
||||
clearKeyManagers();
|
||||
this.keyManagers = keyManagerList;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void clearKeyManagers() {
|
||||
this.certificateChain = null;
|
||||
this.privateKey = null;
|
||||
this.privateKeyPassword = null;
|
||||
this.keyManagers = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the server should expect a client's identity. Must not be {@code null}.
|
||||
* Defaults to {@link ClientAuth#NONE}.
|
||||
*/
|
||||
public Builder clientAuth(ClientAuth clientAuth) {
|
||||
Preconditions.checkNotNull(clientAuth, "clientAuth");
|
||||
this.clientAuth = clientAuth;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the provided root certificates to verify the client's identity instead of the system's
|
||||
* default. Generally they should be PEM-encoded with all the certificates concatenated together
|
||||
* (file header has "BEGIN CERTIFICATE", and would occur once per certificate).
|
||||
*/
|
||||
public Builder trustManager(File rootCerts) throws IOException {
|
||||
InputStream rootCertsIs = new FileInputStream(rootCerts);
|
||||
try {
|
||||
return trustManager(rootCertsIs);
|
||||
} finally {
|
||||
rootCertsIs.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the provided root certificates to verify the client's identity instead of the system's
|
||||
* default. Generally they should be PEM-encoded with all the certificates concatenated together
|
||||
* (file header has "BEGIN CERTIFICATE", and would occur once per certificate).
|
||||
*/
|
||||
public Builder trustManager(InputStream rootCerts) throws IOException {
|
||||
byte[] rootCertsBytes = ByteStreams.toByteArray(rootCerts);
|
||||
clearTrustManagers();
|
||||
this.rootCertificates = rootCertsBytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the provided trust manager verify the client's identity instead of the system's default.
|
||||
* Although multiple are allowed, only the first instance implementing a particular interface is
|
||||
* used. So generally there will just be a single entry and it implements {@link
|
||||
* javax.net.ssl.X509TrustManager}.
|
||||
*/
|
||||
public Builder trustManager(TrustManager... trustManagers) {
|
||||
List<TrustManager> trustManagerList = Collections.unmodifiableList(new ArrayList<>(
|
||||
Arrays.asList(trustManagers)));
|
||||
clearTrustManagers();
|
||||
this.trustManagers = trustManagerList;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void clearTrustManagers() {
|
||||
this.rootCertificates = null;
|
||||
this.trustManagers = null;
|
||||
}
|
||||
|
||||
/** Construct the credentials. */
|
||||
public ServerCredentials build() {
|
||||
if (certificateChain == null) {
|
||||
if (certificateChain == null && keyManagers == null) {
|
||||
throw new IllegalStateException("A key manager is required");
|
||||
}
|
||||
return new TlsServerCredentials(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** The level of authentication the server should expect from the client. */
|
||||
public enum ClientAuth {
|
||||
/** Clients will not present any identity. */
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Clients are requested to present their identity, but clients without identities are
|
||||
* permitted.
|
||||
*/
|
||||
OPTIONAL,
|
||||
|
||||
/**
|
||||
* Clients are requested to present their identity, and are required to provide a valid
|
||||
* identity.
|
||||
*/
|
||||
REQUIRE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue