Skip to content

Commit a72179a

Browse files
evgeniychebanphilwebb
authored andcommitted
Support userInfo in elasticsearch URI
See gh-21381
1 parent abaca95 commit a72179a

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 {
@@ -166,6 +173,70 @@ void restClientCanQueryElasticsearchNode() {
166173
});
167174
}
168175

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

0 commit comments

Comments
 (0)