Rest Client: add callback to customize http client settings

The callback replaces the ability to fully replace the http client instance. By doing that, one used to lose any default that the RestClient had set for the underlying http client. Given that you'd usually override one or two things only, like a couple of timeout values, the ssl factory or the default credentials providers, it is not uder friendly if by doing that users end up replacing the whole http client instance and lose any default set by us.

Original commit: elastic/x-pack-elasticsearch@03adca6f62
This commit is contained in:
javanna 2016-07-11 20:54:43 +02:00 committed by Luca Cavanna
parent 4360cccad7
commit 107ab2d71d
4 changed files with 60 additions and 21 deletions

View File

@ -5,8 +5,6 @@
*/ */
package org.elasticsearch.xpack.security.authc.pki; package org.elasticsearch.xpack.security.authc.pki;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.Response; import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException; import org.elasticsearch.client.ResponseException;
@ -15,16 +13,16 @@ import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.SecuritySettingsSource;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.Security; import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.security.authc.support.SecuredString;
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
import org.elasticsearch.xpack.security.transport.SSLClientAuth; import org.elasticsearch.xpack.security.transport.SSLClientAuth;
import org.elasticsearch.xpack.security.transport.netty.SecurityNettyHttpServerTransport; import org.elasticsearch.xpack.security.transport.netty.SecurityNettyHttpServerTransport;
import org.elasticsearch.xpack.security.transport.netty.SecurityNettyTransport; import org.elasticsearch.xpack.security.transport.netty.SecurityNettyTransport;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.SecuritySettingsSource;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.xpack.XPackPlugin;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
@ -79,8 +77,7 @@ public class PkiOptionalClientAuthTests extends SecurityIntegTestCase {
} }
public void testRestClientWithoutClientCertificate() throws Exception { public void testRestClientWithoutClientCertificate() throws Exception {
CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(getSSLContext()).build(); try (RestClient restClient = createRestClient(new SSLContextHttpConfigCallback(getSSLContext()), "https")) {
try (RestClient restClient = createRestClient(httpClient, "https")) {
try { try {
restClient.performRequest("GET", "_nodes"); restClient.performRequest("GET", "_nodes");
fail("request should have failed"); fail("request should have failed");

View File

@ -6,8 +6,6 @@
package org.elasticsearch.xpack.security.authc.pki; package org.elasticsearch.xpack.security.authc.pki;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.client.Response; import org.elasticsearch.client.Response;
@ -78,8 +76,7 @@ public class PkiWithoutClientAuthenticationTests extends SecurityIntegTestCase {
public void testThatHttpWorks() throws Exception { public void testThatHttpWorks() throws Exception {
SSLContext sc = SSLContext.getInstance("SSL"); SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom()); sc.init(null, trustAllCerts, new SecureRandom());
CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sc).build(); try (RestClient restClient = createRestClient(new SSLContextHttpConfigCallback(sc), "https")) {
try (RestClient restClient = createRestClient(httpClient, "https")) {
try (Response response = restClient.performRequest("GET", "/_nodes", try (Response response = restClient.performRequest("GET", "/_nodes",
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.DEFAULT_USER_NAME, UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.DEFAULT_USER_NAME,

View File

@ -0,0 +1,31 @@
/*
* 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.xpack.security.authc.pki;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.elasticsearch.client.RestClient;
import javax.net.ssl.SSLContext;
class SSLContextHttpConfigCallback implements RestClient.HttpClientConfigCallback {
private final SSLContext sslContext;
SSLContextHttpConfigCallback(SSLContext sslContext) {
this.sslContext = sslContext;
}
@Override
public void customizeDefaultRequestConfig(RequestConfig.Builder requestConfigBuilder) {
}
@Override
public void customizeHttpClient(HttpClientBuilder httpClientBuilder) {
httpClientBuilder.setSSLContext(sslContext);
}
}

View File

@ -5,10 +5,10 @@
*/ */
package org.elasticsearch.xpack.security.transport.ssl; package org.elasticsearch.xpack.security.transport.ssl;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContexts; import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
@ -61,8 +61,7 @@ public class SslClientAuthTests extends SecurityIntegTestCase {
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
SSLContexts.createDefault(), SSLContexts.createDefault(),
NoopHostnameVerifier.INSTANCE); NoopHostnameVerifier.INSTANCE);
try (RestClient restClient = createRestClient(new SSLSocketFactoryHttpConfigCallback(socketFactory), "https")) {
try (RestClient restClient = createRestClient(HttpClients.custom().setSSLSocketFactory(socketFactory).build(), "https")) {
restClient.performRequest("GET", "/"); restClient.performRequest("GET", "/");
fail("Expected SSLHandshakeException"); fail("Expected SSLHandshakeException");
} catch (SSLHandshakeException e) { } catch (SSLHandshakeException e) {
@ -75,14 +74,10 @@ public class SslClientAuthTests extends SecurityIntegTestCase {
.put(getSSLSettingsForStore("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks", "testclient")) .put(getSSLSettingsForStore("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks", "testclient"))
.build(); .build();
ClientSSLService sslService = new ClientSSLService(settings, new Global(settings)); ClientSSLService sslService = new ClientSSLService(settings, new Global(settings));
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
sslService.sslContext(), sslService.sslContext(),
NoopHostnameVerifier.INSTANCE); NoopHostnameVerifier.INSTANCE);
try (RestClient restClient = createRestClient(new SSLSocketFactoryHttpConfigCallback(socketFactory), "https")) {
CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
try (RestClient restClient = createRestClient(client, "https")) {
try (Response response = restClient.performRequest("GET", "/", try (Response response = restClient.performRequest("GET", "/",
new BasicHeader("Authorization", basicAuthHeaderValue(transportClientUsername(), transportClientPassword())))) { new BasicHeader("Authorization", basicAuthHeaderValue(transportClientUsername(), transportClientPassword())))) {
assertThat(response.getStatusLine().getStatusCode(), equalTo(200)); assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
@ -115,4 +110,23 @@ public class SslClientAuthTests extends SecurityIntegTestCase {
assertGreenClusterState(client); assertGreenClusterState(client);
} }
} }
private static class SSLSocketFactoryHttpConfigCallback implements RestClient.HttpClientConfigCallback {
private final SSLConnectionSocketFactory sslSocketFactory;
SSLSocketFactoryHttpConfigCallback(SSLConnectionSocketFactory sslSocketFactory) {
this.sslSocketFactory = sslSocketFactory;
}
@Override
public void customizeDefaultRequestConfig(RequestConfig.Builder requestConfigBuilder) {
}
@Override
public void customizeHttpClient(HttpClientBuilder httpClientBuilder) {
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
}
}
} }