mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-09 06:25:07 +00:00
SSL/TLS: Add option to disable reverse DNS resolution of hostname
This change adds the option to disable reverse DNS lookup of a hostname from an IP address. This is needed if only an IP address is found in a SSL certificate and hostname verification is enabled. Closes elastic/elasticsearch#575 Original commit: elastic/x-pack-elasticsearch@07356bc885
This commit is contained in:
parent
02682ff4ec
commit
166514651a
@ -29,6 +29,7 @@ import java.net.InetSocketAddress;
|
||||
public class NettySecuredTransport extends NettyTransport {
|
||||
|
||||
public static final String HOSTNAME_VERIFICATION_SETTING = "shield.ssl.hostname_verification";
|
||||
public static final String HOSTNAME_VERIFICATION_RESOLVE_NAME_SETTING = "shield.ssl.hostname_verification.resolve_name";
|
||||
|
||||
private final SSLService sslService;
|
||||
private final @Nullable IPFilter authenticator;
|
||||
@ -112,9 +113,7 @@ public class NettySecuredTransport extends NettyTransport {
|
||||
SSLEngine sslEngine;
|
||||
if (settings.getAsBoolean(HOSTNAME_VERIFICATION_SETTING, true)) {
|
||||
InetSocketAddress inetSocketAddress = (InetSocketAddress) e.getValue();
|
||||
String hostname = inetSocketAddress.getHostName();
|
||||
int port = inetSocketAddress.getPort();
|
||||
sslEngine = sslService.createSSLEngine(ImmutableSettings.EMPTY, hostname, port);
|
||||
sslEngine = sslService.createSSLEngine(ImmutableSettings.EMPTY, getHostname(inetSocketAddress), inetSocketAddress.getPort());
|
||||
SSLParameters parameters = new SSLParameters();
|
||||
parameters.setEndpointIdentificationAlgorithm("HTTPS");
|
||||
sslEngine.setSSLParameters(parameters);
|
||||
@ -128,6 +127,20 @@ public class NettySecuredTransport extends NettyTransport {
|
||||
|
||||
ctx.sendDownstream(e);
|
||||
}
|
||||
|
||||
private String getHostname(InetSocketAddress inetSocketAddress) {
|
||||
String hostname;
|
||||
if (settings.getAsBoolean(HOSTNAME_VERIFICATION_RESOLVE_NAME_SETTING, true)) {
|
||||
hostname = inetSocketAddress.getHostName();
|
||||
} else {
|
||||
hostname = inetSocketAddress.getHostString();
|
||||
}
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("resolved hostname [{}] for address [{}] to be used in ssl hostname verification", hostname, inetSocketAddress);
|
||||
}
|
||||
return hostname;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.shield.transport.netty;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
import org.elasticsearch.test.ShieldIntegrationTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
@ClusterScope(scope = ElasticsearchIntegrationTest.Scope.SUITE)
|
||||
public class IPHostnameVerificationIntegrationTests extends ShieldIntegrationTest {
|
||||
|
||||
static Path keystore;
|
||||
|
||||
@Override
|
||||
protected boolean sslTransportEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
Settings settings = super.nodeSettings(nodeOrdinal);
|
||||
// The default Unicast test behavior is to use 'localhost' with the port number. For this test we need to use IP
|
||||
String[] unicastAddresses = settings.getAsArray("discovery.zen.ping.unicast.hosts");
|
||||
for (int i = 0; i < unicastAddresses.length; i++) {
|
||||
String address = unicastAddresses[i];
|
||||
unicastAddresses[i] = address.replace("localhost", "127.0.0.1");
|
||||
}
|
||||
|
||||
ImmutableSettings.Builder settingsBuilder = settingsBuilder()
|
||||
.put(settings)
|
||||
.putArray("discovery.zen.ping.unicast.hosts", unicastAddresses);
|
||||
|
||||
try {
|
||||
//This keystore uses a cert with a CN of "Elasticsearch Test Node" and IPv4+IPv6 ip addresses as SubjectAlternativeNames
|
||||
keystore = Paths.get(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-ip-only.jks").toURI());
|
||||
assertThat(Files.exists(keystore), is(true));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return settingsBuilder.put("shield.ssl.keystore.path", keystore.toAbsolutePath()) // settings for client truststore
|
||||
.put("shield.ssl.keystore.password", "testnode-ip-only")
|
||||
.put("shield.ssl.truststore.path", keystore.toAbsolutePath()) // settings for client truststore
|
||||
.put("shield.ssl.truststore.password", "testnode-ip-only")
|
||||
.put("transport.host", "127.0.0.1")
|
||||
.put("network.host", "127.0.0.1")
|
||||
.put("shield.ssl.client.auth", "false")
|
||||
.put(NettySecuredTransport.HOSTNAME_VERIFICATION_SETTING, true)
|
||||
.put(NettySecuredTransport.HOSTNAME_VERIFICATION_RESOLVE_NAME_SETTING, false)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings transportClientSettings() {
|
||||
return ImmutableSettings.builder().put(super.transportClientSettings())
|
||||
.put(NettySecuredTransport.HOSTNAME_VERIFICATION_SETTING, true)
|
||||
.put(NettySecuredTransport.HOSTNAME_VERIFICATION_RESOLVE_NAME_SETTING, false)
|
||||
.put("shield.ssl.keystore.path", keystore.toAbsolutePath())
|
||||
.put("shield.ssl.keystore.password", "testnode-ip-only")
|
||||
.put("shield.ssl.truststore.path", keystore.toAbsolutePath())
|
||||
.put("shield.ssl.truststore.password", "testnode-ip-only")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransportClientConnectionWorksWithIPOnlyHostnameVerification() throws Exception {
|
||||
Client client = internalCluster().transportClient();
|
||||
assertGreenClusterState(client);
|
||||
}
|
||||
}
|
@ -67,6 +67,7 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
|
||||
private final byte[] systemKey;
|
||||
private final boolean sslTransportEnabled;
|
||||
private final boolean hostnameVerificationEnabled;
|
||||
private final boolean hostnameVerificationResolveNameEnabled;
|
||||
|
||||
/**
|
||||
* Creates a new {@link org.elasticsearch.test.SettingsSource} for the shield configuration.
|
||||
@ -85,7 +86,8 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
|
||||
this.parentFolder = parentFolder;
|
||||
this.subfolderPrefix = scope.name();
|
||||
this.sslTransportEnabled = sslTransportEnabled;
|
||||
hostnameVerificationEnabled = randomBoolean();
|
||||
this.hostnameVerificationEnabled = randomBoolean();
|
||||
this.hostnameVerificationResolveNameEnabled = randomBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -190,11 +192,11 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
|
||||
}
|
||||
|
||||
private Settings getNodeSSLSettings() {
|
||||
return getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks", "testnode", sslTransportEnabled, hostnameVerificationEnabled);
|
||||
return getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks", "testnode", sslTransportEnabled, hostnameVerificationEnabled, hostnameVerificationResolveNameEnabled);
|
||||
}
|
||||
|
||||
private Settings getClientSSLSettings() {
|
||||
return getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks", "testclient", sslTransportEnabled, hostnameVerificationEnabled);
|
||||
return getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks", "testclient", sslTransportEnabled, hostnameVerificationEnabled, hostnameVerificationResolveNameEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -205,10 +207,10 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
|
||||
* @return the configuration settings
|
||||
*/
|
||||
public static Settings getSSLSettingsForStore(String resourcePathToStore, String password) {
|
||||
return getSSLSettingsForStore(resourcePathToStore, password, true, true);
|
||||
return getSSLSettingsForStore(resourcePathToStore, password, true, true, true);
|
||||
}
|
||||
|
||||
private static Settings getSSLSettingsForStore(String resourcePathToStore, String password, boolean sslTransportEnabled, boolean hostnameVerificationEnabled) {
|
||||
private static Settings getSSLSettingsForStore(String resourcePathToStore, String password, boolean sslTransportEnabled, boolean hostnameVerificationEnabled, boolean hostnameVerificationResolveNameEnabled) {
|
||||
File store;
|
||||
try {
|
||||
store = new File(ShieldSettingsSource.class.getResource(resourcePathToStore).toURI());
|
||||
@ -227,7 +229,8 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
|
||||
if (sslTransportEnabled) {
|
||||
builder.put("shield.ssl.keystore.path", store.getPath())
|
||||
.put("shield.ssl.keystore.password", password)
|
||||
.put(NettySecuredTransport.HOSTNAME_VERIFICATION_SETTING, hostnameVerificationEnabled);
|
||||
.put(NettySecuredTransport.HOSTNAME_VERIFICATION_SETTING, hostnameVerificationEnabled)
|
||||
.put(NettySecuredTransport.HOSTNAME_VERIFICATION_RESOLVE_NAME_SETTING, hostnameVerificationResolveNameEnabled);
|
||||
}
|
||||
|
||||
if (sslTransportEnabled && randomBoolean()) {
|
||||
|
@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDYjCCAkqgAwIBAgIJAKP3WbDN1WxEMA0GCSqGSIb3DQEBCwUAMEgxDDAKBgNV
|
||||
BAoTA29yZzEWMBQGA1UECxMNZWxhc3RpY3NlYXJjaDEgMB4GA1UEAxMXRWxhc3Rp
|
||||
Y3NlYXJjaCBUZXN0IE5vZGUwHhcNMTUwMTE5MTQwNDE3WhcNMTkwMTE4MTQwNDE3
|
||||
WjBIMQwwCgYDVQQKEwNvcmcxFjAUBgNVBAsTDWVsYXN0aWNzZWFyY2gxIDAeBgNV
|
||||
BAMTF0VsYXN0aWNzZWFyY2ggVGVzdCBOb2RlMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEA3a5+yBl2rVEGwlOjw6Ji43+iqvaAbmVhnCk6laEa3GpzothX
|
||||
7HhtGGDfjdhaLzWF5PWP8SvMM8g4f1PLN0hGSR7vrWjlnpvUDXIHsoIRqWfYdwDA
|
||||
RNiUvOI4FBjN4pZ4sXyUYsTpw80l6W0r3zopyycE4+4HJv55U1Yy2/3qzv1IITqD
|
||||
LwRt6VpbPGVyzDSBMQXEgfT7sfaJB9Ru+A/onIpEicrWhgCPHrBnSUkKCKNj9AX/
|
||||
RV6/yQYnS/KhLx/eQTP7NVcbrC2J4fFOLX9oZAj6dir/tYQ6rDAMqBTnbhGygDqP
|
||||
0RgCVf82n6mA23n7l5DaZ4RZl+ssN3fNqDyDpQIDAQABo08wTTAJBgNVHRMEAjAA
|
||||
MB0GA1UdDgQWBBSDFYaN/Od9ad7Kztv6cGjd2X4w1TAhBgNVHREEGjAYhwR/AAAB
|
||||
hxAAAAAAAAAAAAAAAAAAAAACMA0GCSqGSIb3DQEBCwUAA4IBAQCbxk4VHMcdD2yU
|
||||
VpLSBxHBdWY/Gn3f7k0WWhQAmRPR+S6vSr89hVO8UIkqEFzc+D19s9h0XvAmo2QO
|
||||
G80OLTcHIjxiVqAVWoGUPH4D7FdG7sSBbrJbweIBMW8Ba4kefWGcI0KlUWTssFyE
|
||||
YLJQIUCIdKtVf/qmcItvrEXw8ucSYaExvizMClTvf2fZxRws8Omo3dxn+ifUH5nn
|
||||
evQW8Tawlx2ql5P6wHTSUclGLv1CXtMAnuOlyaYY/UbslNhSXigxYOZCI3ole3qL
|
||||
Z0dBah+eCspOit14mi7jHPoS1Yji/CSh33KZD6ZESuv/V1B7oy6zZWei/b4vllW5
|
||||
RwZx1Y/r
|
||||
-----END CERTIFICATE-----
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user