mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-25 19:09:03 +00:00
Merge pull request #46167 from l-trotta
* gh-46167: Polish "Add support for Elasticsearch API-key-based authentication" Add support for Elasticsearch API-key-based authentication Closes gh-46167
This commit is contained in:
+8
@@ -57,6 +57,14 @@ public interface ElasticsearchConnectionDetails extends ConnectionDetails {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* APIKey for authentication with Elasticsearch.
|
||||
* @return the API key for authentication with Elasticsearch or {@code null}
|
||||
*/
|
||||
default @Nullable String getApiKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefix added to the path of every request sent to Elasticsearch.
|
||||
* @return prefix added to the path of every request sent to Elasticsearch or
|
||||
|
||||
+13
@@ -49,6 +49,11 @@ public class ElasticsearchProperties {
|
||||
*/
|
||||
private @Nullable String password;
|
||||
|
||||
/**
|
||||
* API key for authentication with Elasticsearch.
|
||||
*/
|
||||
private @Nullable String apiKey;
|
||||
|
||||
/**
|
||||
* Connection timeout used when communicating with Elasticsearch.
|
||||
*/
|
||||
@@ -95,6 +100,14 @@ public class ElasticsearchProperties {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public @Nullable String getApiKey() {
|
||||
return this.apiKey;
|
||||
}
|
||||
|
||||
public void setApiKey(@Nullable String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
public Duration getConnectionTimeout() {
|
||||
return this.connectionTimeout;
|
||||
}
|
||||
|
||||
+12
@@ -36,7 +36,9 @@ import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
|
||||
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
|
||||
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
|
||||
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.message.BasicHeader;
|
||||
import org.apache.hc.core5.reactor.IOReactorConfig;
|
||||
import org.apache.hc.core5.reactor.ssl.SSLBufferMode;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
@@ -67,6 +69,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @author Laura Trotta
|
||||
*/
|
||||
class ElasticsearchRestClientConfigurations {
|
||||
|
||||
@@ -99,6 +102,10 @@ class ElasticsearchRestClientConfigurations {
|
||||
.stream()
|
||||
.map((node) -> new HttpHost(node.protocol().getScheme(), node.hostname(), node.port()))
|
||||
.toArray(HttpHost[]::new));
|
||||
if (connectionDetails.getApiKey() != null) {
|
||||
builder.setDefaultHeaders(
|
||||
new Header[] { new BasicHeader("Authorization", "ApiKey " + connectionDetails.getApiKey()), });
|
||||
}
|
||||
builder.setHttpClientConfigCallback((httpClientBuilder) -> builderCustomizers.orderedStream()
|
||||
.forEach((customizer) -> customizer.customize(httpClientBuilder)));
|
||||
builder.setConnectionManagerCallback((connectionManagerBuilder) -> builderCustomizers.orderedStream()
|
||||
@@ -275,6 +282,11 @@ class ElasticsearchRestClientConfigurations {
|
||||
return this.properties.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getApiKey() {
|
||||
return this.properties.getApiKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getPathPrefix() {
|
||||
return this.properties.getPathPrefix();
|
||||
|
||||
+37
@@ -33,6 +33,7 @@ import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
|
||||
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
|
||||
import org.apache.hc.core5.function.Resolver;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.config.Registry;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
@@ -62,6 +63,7 @@ import static org.mockito.Mockito.mock;
|
||||
* @author Andy Wilkinson
|
||||
* @author Moritz Halbritter
|
||||
* @author Phillip Webb
|
||||
* @author Laura Trotta
|
||||
*/
|
||||
class ElasticsearchRestClientAutoConfigurationTests {
|
||||
|
||||
@@ -193,6 +195,41 @@ class ElasticsearchRestClientAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenApiKeyIsConfiguredThenAuthorizationHeaderIsPresent() {
|
||||
this.contextRunner.withPropertyValues("spring.elasticsearch.api-key=some-api-key").run((context) -> {
|
||||
Rest5Client client = context.getBean(Rest5Client.class);
|
||||
assertThat(client).extracting("defaultHeaders", InstanceOfAssertFactories.list(Header.class))
|
||||
.satisfiesOnlyOnce((header) -> {
|
||||
assertThat(header.getName().equals("Authorization"));
|
||||
assertThat(header.getValue().equals("ApiKey some-api-key"));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenApiKeyAndUsernameAndPasswordAreConfiguredThenBothFormsOfCredentialsArePresent() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.elasticsearch.api-key=some-api-key", "spring.elasticsearch.username=alice",
|
||||
"spring.elasticsearch.password=secret")
|
||||
.run((context) -> {
|
||||
Rest5Client client = context.getBean(Rest5Client.class);
|
||||
assertThat(client).extracting("defaultHeaders", InstanceOfAssertFactories.list(Header.class))
|
||||
.satisfiesOnlyOnce((header) -> {
|
||||
assertThat(header.getName().equals("Authorization"));
|
||||
assertThat(header.getValue().equals("ApiKey some-api-key"));
|
||||
});
|
||||
assertThat(client)
|
||||
.extracting("client.credentialsProvider", InstanceOfAssertFactories.type(CredentialsProvider.class))
|
||||
.satisfies((credentialsProvider) -> {
|
||||
UsernamePasswordCredentials defaultCredentials = (UsernamePasswordCredentials) credentialsProvider
|
||||
.getCredentials(new AuthScope(null, -1), null);
|
||||
assertThat(defaultCredentials.getUserPrincipal().getName()).isEqualTo("alice");
|
||||
assertThat(defaultCredentials.getUserPassword()).containsExactly("secret".toCharArray());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void configureWithCustomPathPrefix() {
|
||||
this.contextRunner.withPropertyValues("spring.elasticsearch.path-prefix=/some/prefix").run((context) -> {
|
||||
|
||||
Reference in New Issue
Block a user