Hi,
The used SSL context does not send the SNIServerNames SSLProperty when SSL verification is disabled.
So when Vault is running e.g. in OpenShift it does not work because it does not know where to route the requests.
Basically the SSLSocketFactory needs to set the right server name to the created SSLSocket.
There is also the way to do this on our own by setting a custom SSLContext in the SSLConfig, but then the HostnameVerifier is not set to the one which just allows everything and it still fails.
I had to do a dirty hack to get it working and it will also only work for one vault connection in the whole JVM:
final SSLContext sslContext = SSLContext.getInstance("TLS");
SSLContextSpi spi = new SSLContextSpi() {
@Override
protected void engineInit(final KeyManager[] km, final TrustManager[] tm, final SecureRandom sr) throws KeyManagementException {
sslContext.init(km, tm, sr);
}
@Override
protected SSLSocketFactory engineGetSocketFactory() {
SSLParameters params = new SSLParameters();
params.setServerNames(Arrays.asList(new SNIHostName("my-vault-connector.foobar.com")));
return new SSLSocketFactoryWrapper(sslContext.getSocketFactory(), params);
}
@Override
protected SSLServerSocketFactory engineGetServerSocketFactory() {
return sslContext.getServerSocketFactory();
}
@Override
protected SSLSessionContext engineGetServerSessionContext() {
return sslContext.getServerSessionContext();
}
@Override
protected SSLSessionContext engineGetClientSessionContext() {
return sslContext.getClientSessionContext();
}
@Override
protected SSLEngine engineCreateSSLEngine(final String host, final int port) {
return sslContext.createSSLEngine(host, port);
}
@Override
protected SSLEngine engineCreateSSLEngine() {
return sslContext.createSSLEngine();
}
};
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(final X509Certificate[] x509Certificates, final String s)
throws CertificateException {
}
@Override
public void checkServerTrusted(final X509Certificate[] x509Certificates, final String s)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
} }, new java.security.SecureRandom());
class SSLContextWrapper extends SSLContext {
public SSLContextWrapper(final SSLContextSpi spi, final java.security.Provider provider, final String protocol) {
super(spi, provider, protocol);
}
}
Field field = Rest.class.getDeclaredField("DISABLED_SSL_CONTEXT");
field.setAccessible(true);
field.set(null, new SSLContextWrapper(spi, sslContext.getProvider(), sslContext.getProtocol()));
vault = new Vault(new VaultConfig()
.address(address)
.token(token)
.sslConfig(new SslConfig().verify(false).build())
.build());
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class SSLSocketFactoryWrapper extends SSLSocketFactory {
private final SSLSocketFactory wrappedFactory;
private final SSLParameters sslParameters;
public SSLSocketFactoryWrapper(final SSLSocketFactory factory, final SSLParameters sslParameters) {
this.wrappedFactory = factory;
this.sslParameters = sslParameters;
}
@Override
public Socket createSocket(final String host, final int port) throws IOException, UnknownHostException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port);
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public Socket createSocket(final String host, final int port, final InetAddress localHost, final int localPort)
throws IOException, UnknownHostException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port, localHost, localPort);
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public Socket createSocket(final InetAddress host, final int port) throws IOException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port);
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public Socket createSocket(final InetAddress address, final int port, final InetAddress localAddress,
final int localPort) throws IOException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(address, port, localAddress, localPort);
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public Socket createSocket() throws IOException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket();
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public String[] getDefaultCipherSuites() {
return wrappedFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return wrappedFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket(final Socket s, final String host, final int port, final boolean autoClose)
throws IOException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(s, host, port, autoClose);
socket.setSSLParameters(sslParameters);
return socket;
}
}
Hi, The used SSL context does not send the SNIServerNames SSLProperty when SSL verification is disabled. So when Vault is running e.g. in OpenShift it does not work because it does not know where to route the requests.
Basically the SSLSocketFactory needs to set the right server name to the created SSLSocket. There is also the way to do this on our own by setting a custom SSLContext in the SSLConfig, but then the HostnameVerifier is not set to the one which just allows everything and it still fails.
I had to do a dirty hack to get it working and it will also only work for one vault connection in the whole JVM: