Skip to content

Commit 964e712

Browse files
committed
Support userInfo in elasticsearch uri
Fixes gh-21291
1 parent 7afd25f commit 964e712

File tree

2 files changed

+99
-3
lines changed

2 files changed

+99
-3
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientConfigurations.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.boot.autoconfigure.elasticsearch;
1818

19+
import java.net.URI;
1920
import java.time.Duration;
2021

2122
import org.apache.http.HttpHost;
@@ -43,6 +44,7 @@
4344
* @author Brian Clozel
4445
* @author Stephane Nicoll
4546
* @author Vedran Pavic
47+
* @author Evgeniy Cheban
4648
*/
4749
class ElasticsearchRestClientConfigurations {
4850

@@ -58,7 +60,7 @@ RestClientBuilderCustomizer defaultRestClientBuilderCustomizer(ElasticsearchRest
5860
@Bean
5961
RestClientBuilder elasticsearchRestClientBuilder(ElasticsearchRestClientProperties properties,
6062
ObjectProvider<RestClientBuilderCustomizer> builderCustomizers) {
61-
HttpHost[] hosts = properties.getUris().stream().map(HttpHost::create).toArray(HttpHost[]::new);
63+
HttpHost[] hosts = properties.getUris().stream().map(this::createHttpHost).toArray(HttpHost[]::new);
6264
RestClientBuilder builder = RestClient.builder(hosts);
6365
builder.setHttpClientConfigCallback((httpClientBuilder) -> {
6466
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(httpClientBuilder));
@@ -72,6 +74,12 @@ RestClientBuilder elasticsearchRestClientBuilder(ElasticsearchRestClientProperti
7274
return builder;
7375
}
7476

77+
private HttpHost createHttpHost(String uri) {
78+
URI parsedUri = URI.create(uri);
79+
String userInfo = parsedUri.getUserInfo();
80+
return HttpHost.create((userInfo != null) ? uri.replace(userInfo + "@", "") : uri);
81+
}
82+
7583
}
7684

7785
@Configuration(proxyBeanMethods = false)
@@ -124,15 +132,32 @@ public void customize(RestClientBuilder builder) {
124132

125133
@Override
126134
public void customize(HttpAsyncClientBuilder builder) {
135+
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
136+
builder.setDefaultCredentialsProvider(credentialsProvider);
137+
this.properties.getUris().stream().map(URI::create).filter((uri) -> uri.getUserInfo() != null)
138+
.forEach((uri) -> {
139+
AuthScope authScope = new AuthScope(uri.getHost(), uri.getPort());
140+
Credentials credentials = createCredentials(uri.getUserInfo());
141+
credentialsProvider.setCredentials(authScope, credentials);
142+
});
127143
map.from(this.properties::getUsername).whenHasText().to((username) -> {
128-
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
129144
Credentials credentials = new UsernamePasswordCredentials(this.properties.getUsername(),
130145
this.properties.getPassword());
131146
credentialsProvider.setCredentials(AuthScope.ANY, credentials);
132-
builder.setDefaultCredentialsProvider(credentialsProvider);
133147
});
134148
}
135149

150+
private Credentials createCredentials(String usernameAndPassword) {
151+
int delimiter = usernameAndPassword.indexOf(":");
152+
if (delimiter == -1) {
153+
return new UsernamePasswordCredentials(usernameAndPassword, null);
154+
}
155+
156+
String username = usernameAndPassword.substring(0, delimiter);
157+
String password = usernameAndPassword.substring(delimiter + 1);
158+
return new UsernamePasswordCredentials(username, password);
159+
}
160+
136161
@Override
137162
public void customize(RequestConfig.Builder builder) {
138163
map.from(this.properties::getConnectionTimeout).whenNonNull().asInt(Duration::toMillis)

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientAutoConfigurationTests.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,16 @@
2020
import java.util.HashMap;
2121
import java.util.Map;
2222

23+
import org.apache.http.HttpHost;
24+
import org.apache.http.auth.AuthScope;
25+
import org.apache.http.auth.Credentials;
26+
import org.apache.http.client.CredentialsProvider;
2327
import org.apache.http.client.config.RequestConfig;
2428
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
29+
import org.assertj.core.api.InstanceOfAssertFactories;
2530
import org.elasticsearch.action.get.GetRequest;
2631
import org.elasticsearch.action.index.IndexRequest;
32+
import org.elasticsearch.client.Node;
2733
import org.elasticsearch.client.RequestOptions;
2834
import org.elasticsearch.client.RestClient;
2935
import org.elasticsearch.client.RestClientBuilder;
@@ -47,6 +53,7 @@
4753
*
4854
* @author Brian Clozel
4955
* @author Vedran Pavic
56+
* @author Evgeniy Cheban
5057
*/
5158
@Testcontainers(disabledWithoutDocker = true)
5259
class ElasticsearchRestClientAutoConfigurationTests {
@@ -156,6 +163,70 @@ void restClientCanQueryElasticsearchNode() {
156163
});
157164
}
158165

166+
@Test
167+
void configureUriWithUsernameOnly() {
168+
this.contextRunner.withPropertyValues("spring.elasticsearch.rest.uris=http://user@localhost:9200")
169+
.run((context) -> {
170+
RestClient client = context.getBean(RestClient.class);
171+
assertThat(client.getNodes().stream().map(Node::getHost).map(HttpHost::toString))
172+
.containsExactly("http://localhost:9200");
173+
assertThat(client).extracting("client")
174+
.extracting("credentialsProvider",
175+
InstanceOfAssertFactories.type(CredentialsProvider.class))
176+
.satisfies((credentialsProvider) -> {
177+
Credentials credentials = credentialsProvider
178+
.getCredentials(new AuthScope("localhost", 9200));
179+
assertThat(credentials.getUserPrincipal().getName()).isEqualTo("user");
180+
assertThat(credentials.getPassword()).isNull();
181+
});
182+
});
183+
}
184+
185+
@Test
186+
void configureUriWithUsernameAndEmptyPassword() {
187+
this.contextRunner.withPropertyValues("spring.elasticsearch.rest.uris=http://user:@localhost:9200")
188+
.run((context) -> {
189+
RestClient client = context.getBean(RestClient.class);
190+
assertThat(client.getNodes().stream().map(Node::getHost).map(HttpHost::toString))
191+
.containsExactly("http://localhost:9200");
192+
assertThat(client).extracting("client")
193+
.extracting("credentialsProvider",
194+
InstanceOfAssertFactories.type(CredentialsProvider.class))
195+
.satisfies((credentialsProvider) -> {
196+
Credentials credentials = credentialsProvider
197+
.getCredentials(new AuthScope("localhost", 9200));
198+
assertThat(credentials.getUserPrincipal().getName()).isEqualTo("user");
199+
assertThat(credentials.getPassword()).isEmpty();
200+
});
201+
});
202+
}
203+
204+
@Test
205+
void configureUriWithUsernameAndPasswordWhenUsernameAndPasswordPropertiesSet() {
206+
this.contextRunner
207+
.withPropertyValues("spring.elasticsearch.rest.uris=http://user:password@localhost:9200,localhost:9201",
208+
"spring.elasticsearch.rest.username=admin", "spring.elasticsearch.rest.password=admin")
209+
.run((context) -> {
210+
RestClient client = context.getBean(RestClient.class);
211+
assertThat(client.getNodes().stream().map(Node::getHost).map(HttpHost::toString))
212+
.containsExactly("http://localhost:9200", "http://localhost:9201");
213+
assertThat(client).extracting("client")
214+
.extracting("credentialsProvider",
215+
InstanceOfAssertFactories.type(CredentialsProvider.class))
216+
.satisfies((credentialsProvider) -> {
217+
Credentials uriCredentials = credentialsProvider
218+
.getCredentials(new AuthScope("localhost", 9200));
219+
assertThat(uriCredentials.getUserPrincipal().getName()).isEqualTo("user");
220+
assertThat(uriCredentials.getPassword()).isEqualTo("password");
221+
222+
Credentials defaultCredentials = credentialsProvider
223+
.getCredentials(new AuthScope("localhost", 9201));
224+
assertThat(defaultCredentials.getUserPrincipal().getName()).isEqualTo("admin");
225+
assertThat(defaultCredentials.getPassword()).isEqualTo("admin");
226+
});
227+
});
228+
}
229+
159230
@Configuration(proxyBeanMethods = false)
160231
static class CustomRestClientConfiguration {
161232

0 commit comments

Comments
 (0)