1

Overview:

I tried non-secure connection between API and my local elasticsearch and everything worked well. To do securing connection, I did the following steps to add xpack plugin on my elastic and used it in the api:

  • From the elastic part, I installed xpack based on Install xpack and everything is fine outside of Api. Then added username api with password apipass as a new elastic super user.
  • From API side, I updated the code as follows for secure connection: Java Client and Security

My code changes in elastic configurations:

@Bean
public TransportClient transportClient() throws UnknownHostException {
    Settings settings = Settings.builder()
        .put("cluster.name", clusterName)
        .put("xpack.security.user", "api:apipass")
        .build();
    try (TransportClient client = new PreBuiltXPackTransportClient(settings)
        .addTransportAddress(new TransportAddress(InetAddress.getByName(host), tcpPort))) {            
        String token = basicAuthHeaderValue("api", new SecureString("apipass".toCharArray()));
        client.filterWithHeader(Collections.singletonMap("Authorization", token))
            .prepareSearch().get();

        return client;
    }
}

Issue:

When trying to run the elastic query via application, the following exception will be raised:

Caused by: java.lang.IllegalStateException: transport client is closed
at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:243) ~[elasticsearch-6.0.0.jar:6.0.0]
at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:59) ~[elasticsearch-6.0.0.jar:6.0.0]
at org.elasticsearch.client.transport.TransportClient.doExecute(TransportClient.java:357) ~[elasticsearch-6.0.0.jar:6.0.0]
at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:405) ~[elasticsearch-6.0.0.jar:6.0.0]
at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:394) ~[elasticsearch-6.0.0.jar:6.0.0]
at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:46) ~[elasticsearch-6.0.0.jar:6.0.0]
at org.elasticsearch.action.ActionRequestBuilder.get(ActionRequestBuilder.java:53) ~[elasticsearch-6.0.0.jar:6.0.0]

I would appreciate if anyone could share their genuine solution with me to connect Spring boot application to elasticsearch with basic authentication?

0

3 Answers 3

6

If you using <artifactId>spring-boot-starter-data-elasticsearch</artifactId> dependency you need specify username and password via Basic Authentication.

import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

@Configuration
@EnableElasticsearchRepositories(basePackages = "yourpackage.domain.elastic")
public class ElasticConfig {
    @Value("${elasticsearch.host}")
    private String host;
    @Value("${elasticsearch.username}")
    private String username;
    @Value("${elasticsearch.password}")
    private String password;

    @Bean
    public RestHighLevelClient client() {
        ClientConfiguration clientConfiguration
                = ClientConfiguration.builder()
                .connectedTo(host)
                .withBasicAuth(username, password) // put your credentials
                .build();
        return RestClients.create(clientConfiguration).rest();
    }

    @Bean
    public ElasticsearchOperations elasticsearchTemplate() {
        return new ElasticsearchRestTemplate(client());
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1
    final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY,
            new UsernamePasswordCredentials("username", "password"));

    final RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200))
            .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                @Override
                public HttpAsyncClientBuilder customizeHttpClient(
                        HttpAsyncClientBuilder httpClientBuilder) {
                    httpClientBuilder.disableAuthCaching();
                    return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                }
            });

    final RestClient restClient = builder.build();
    final Response result = restClient.performRequest("GET", "_index/blahblah",
                Collections.emptyMap());

@saeedj: I followed https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.x/_basic_authentication.html

You can try it :)

2 Comments

How can we do this without basic auth , let say read accesskey and secrets from a file and do it ?
@VaibhavMishra: elastic.co/guide/en/elasticsearch/client/java-api-client/… I think you can get key, secret from file and implement RestClientBuilder with apiKeyAuth
1

Remove the transport client from the Try-with-resources, the client is being closed when you leave the "try". You may have an error from Sonar or similar code reviewer. That was the solution I found.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.