I want to insert (index) some data into Elastic Search running in Elastic Cloud in a Java application.
To do so, I wrote the following piece of code:
void sendStuffToElasticSearch() {
RestHighLevelClient client = null;
try {
client = new RestHighLevelClient(
RestClient.builder(CLOUD_ID)
);
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
builder.addHeader("Authorization", String.format("ApiKey %s",
API_KEY));
final RequestOptions requestOptions = builder.build();
IndexRequest request = new IndexRequest("posts");
request.id("1");
String jsonString = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";
request.source(jsonString, XContentType.JSON);
IndexResponse indexResponse = client.index(request, requestOptions);
System.out.println("indexResponse");
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(client);
}
}
API_KEY
is the key I generated according to this tutorial which also says I need to send it in the Authorization
header in the following format: Authorization: ApiKey $EC_API_KEY
.
When I run the above code, I am getting the following error:
org.elasticsearch.client.ResponseException: method [PUT], host [https://XXXXXXXXXX:9243], URI [/posts/_doc/1?timeout=1m], status line [HTTP/1.1 401 Unauthorized]
{"error":{"root_cause":[{"type":"security_exception","reason":"missing authentication credentials for REST request [/posts/_doc/1?timeout=1m]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}}],"type":"security_exception","reason":"missing authentication credentials for REST request [/posts/_doc/1?timeout=1m]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}},"status":401}
at org.elasticsearch.client.RestClient.convertResponse(RestClient.java:326)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:296)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:270)
at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1621)
... 30 more
How can fix this, i. e. provide all authentication-related data in the way Elastic Cloud expects them?
I am using following libraries:
<properties>
[...]
<elastic-search-client.version>7.11.1</elastic-search-client.version>
</properties>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>${elastic-search-client.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elastic-search-client.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elastic-search-client.version}</version>
</dependency>
Update 1: Base64-encoding of the API key as suggested here (see code below) did not help.
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
builder.addHeader("Authorization", String.format("ApiKey %s",
Base64.getEncoder().encodeToString(API_KEY.getBytes(StandardCharsets.UTF_8))));
final RequestOptions requestOptions = builder.build();
Update 2: Changing the way I create the client, did not help, either (see below).
Header[] defaultHeaders =
new Header[]{new BasicHeader("Authorization",
String.format("ApiKey %s",API_KEY))};
final RestClientBuilder builder1 = RestClient.builder(CLOUD_ID);
builder1.setDefaultHeaders(defaultHeaders);
client = new RestHighLevelClient(
builder1
);
Update 3: I changed the supplied API key to
public static final String BASE64_API_KEY = Base64.getEncoder().encodeToString(String.format("%s:%s", ID, KEY).getBytes());
as suggested by Ricardo Ferreira.
Now I am getting a different error:
org.elasticsearch.client.ResponseException: method [PUT], host [XXXXXXXXXXXXXXXX], URI [/posts/_doc/1?timeout=1m], status line [HTTP/1.1 403 Forbidden]
{"error":{"root_cause":[{"type":"security_exception","reason":"action [indices:admin/auto_create] is unauthorized for API key id [XXXXXXXXXXXXXXXX] of user [XXXXXXXXXXXXXXXX]"}],"type":"security_exception","reason":"action [indices:admin/auto_create] is unauthorized for API key id [XXXXXXXXXXXXXXXX] of user [XXXXXXXXXXXXXXXX]"},"status":403}
at org.elasticsearch.client.RestClient.convertResponse(RestClient.java:326)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:296)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:270)
at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1621)
... 30 more
Update 4:
After I created the index in question, the error message changed to this:
org.elasticsearch.client.ResponseException: method [PUT], host [XXXXXXXXXXXXXXXX], URI [/camunda-1/_doc/1?timeout=1m], status line [HTTP/1.1 403 Forbidden]
{"error":{"root_cause":[{"type":"security_exception","reason":"action [indices:data/write/bulk[s]] is unauthorized for API key id [XXXXXXXXXXXXXXXX] of user [XXXXXXXXXXXXXXXX]"}],"type":"security_exception","reason":"action [indices:data/write/bulk[s]] is unauthorized for API key id [XXXXXXXXXXXXXXXX] of user [XXXXXXXXXXXXXXXX]"},"status":403}